rulesync 0.41.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/{chunk-SXEFNT27.js → chunk-2FR4Z37J.js} +1 -1
- package/dist/{chunk-CUKKFQFO.js → chunk-B3627VQY.js} +9 -7
- package/dist/{chunk-PPX47BRK.js → chunk-RL3TE3EZ.js} +6 -6
- package/dist/{chunk-QR656A7R.js → chunk-TCK42GOL.js} +2 -2
- package/dist/chunk-THWXK5Z2.js +35 -0
- package/dist/{chunk-XN7RGMJW.js → chunk-XHRBWFGI.js} +2 -2
- package/dist/{chunk-4SFPBBIB.js → chunk-ZMAL5LIX.js} +8 -3
- package/dist/{claude-JS6ARGB3.js → claudecode-ITHKV345.js} +2 -2
- package/dist/{cline-MM3R4QQE.js → cline-PKE6TYNJ.js} +2 -2
- package/dist/{copilot-NLSI3ID7.js → copilot-5JP6D4NO.js} +2 -2
- package/dist/{cursor-AU3PRMGD.js → cursor-RHFDG6T2.js} +2 -2
- package/dist/{geminicli-LINS3RMZ.js → geminicli-B3FFO5WV.js} +2 -2
- package/dist/index.cjs +143 -182
- package/dist/index.js +111 -129
- package/dist/{roo-KUGAURJB.js → roo-UOTKEOH7.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-6YNGMPAL.js +0 -56
package/dist/index.cjs
CHANGED
|
@@ -26,44 +26,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
|
|
29
|
-
// src/
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
"src/
|
|
29
|
+
// src/types/tool-targets.ts
|
|
30
|
+
var import_v42, ToolTargetSchema, ToolTargetsSchema, WildcardTargetSchema, RulesyncTargetsSchema;
|
|
31
|
+
var init_tool_targets = __esm({
|
|
32
|
+
"src/types/tool-targets.ts"() {
|
|
33
33
|
"use strict";
|
|
34
|
-
|
|
35
|
-
ToolTargetSchema =
|
|
34
|
+
import_v42 = require("zod/v4");
|
|
35
|
+
ToolTargetSchema = import_v42.z.enum([
|
|
36
36
|
"copilot",
|
|
37
37
|
"cursor",
|
|
38
38
|
"cline",
|
|
39
39
|
"claudecode",
|
|
40
|
-
"claude",
|
|
41
40
|
"roo",
|
|
42
41
|
"geminicli"
|
|
43
42
|
]);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
RulesyncTargetsSchema =
|
|
47
|
-
McpTransportTypeSchema = import_zod.z.enum(["stdio", "sse", "http"]);
|
|
48
|
-
McpServerBaseSchema = import_zod.z.object({
|
|
49
|
-
command: import_zod.z.string().optional(),
|
|
50
|
-
args: import_zod.z.array(import_zod.z.string()).optional(),
|
|
51
|
-
url: import_zod.z.string().optional(),
|
|
52
|
-
httpUrl: import_zod.z.string().optional(),
|
|
53
|
-
env: import_zod.z.record(import_zod.z.string()).optional(),
|
|
54
|
-
disabled: import_zod.z.boolean().optional(),
|
|
55
|
-
networkTimeout: import_zod.z.number().optional(),
|
|
56
|
-
timeout: import_zod.z.number().optional(),
|
|
57
|
-
trust: import_zod.z.boolean().optional(),
|
|
58
|
-
cwd: import_zod.z.string().optional(),
|
|
59
|
-
transport: McpTransportTypeSchema.optional(),
|
|
60
|
-
type: import_zod.z.enum(["sse", "streamable-http"]).optional(),
|
|
61
|
-
alwaysAllow: import_zod.z.array(import_zod.z.string()).optional(),
|
|
62
|
-
tools: import_zod.z.array(import_zod.z.string()).optional()
|
|
63
|
-
});
|
|
64
|
-
RulesyncMcpServerSchema = McpServerBaseSchema.extend({
|
|
65
|
-
targets: RulesyncTargetsSchema.optional()
|
|
66
|
-
});
|
|
43
|
+
ToolTargetsSchema = import_v42.z.array(ToolTargetSchema);
|
|
44
|
+
WildcardTargetSchema = import_v42.z.tuple([import_v42.z.literal("*")]);
|
|
45
|
+
RulesyncTargetsSchema = import_v42.z.union([ToolTargetsSchema, WildcardTargetSchema]);
|
|
67
46
|
}
|
|
68
47
|
});
|
|
69
48
|
|
|
@@ -87,17 +66,17 @@ function shouldIncludeServer(server, targetTool) {
|
|
|
87
66
|
var init_mcp_helpers = __esm({
|
|
88
67
|
"src/utils/mcp-helpers.ts"() {
|
|
89
68
|
"use strict";
|
|
90
|
-
|
|
69
|
+
init_tool_targets();
|
|
91
70
|
}
|
|
92
71
|
});
|
|
93
72
|
|
|
94
|
-
// src/generators/mcp/
|
|
95
|
-
function generateClaudeMcp(config
|
|
73
|
+
// src/generators/mcp/claudecode.ts
|
|
74
|
+
function generateClaudeMcp(config) {
|
|
96
75
|
const claudeSettings = {
|
|
97
76
|
mcpServers: {}
|
|
98
77
|
};
|
|
99
78
|
const shouldInclude = (server) => {
|
|
100
|
-
return shouldIncludeServer(server, "
|
|
79
|
+
return shouldIncludeServer(server, "claudecode");
|
|
101
80
|
};
|
|
102
81
|
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
103
82
|
if (!shouldInclude(server)) continue;
|
|
@@ -123,15 +102,15 @@ function generateClaudeMcp(config, _target) {
|
|
|
123
102
|
}
|
|
124
103
|
return JSON.stringify(claudeSettings, null, 2);
|
|
125
104
|
}
|
|
126
|
-
var
|
|
127
|
-
"src/generators/mcp/
|
|
105
|
+
var init_claudecode = __esm({
|
|
106
|
+
"src/generators/mcp/claudecode.ts"() {
|
|
128
107
|
"use strict";
|
|
129
108
|
init_mcp_helpers();
|
|
130
109
|
}
|
|
131
110
|
});
|
|
132
111
|
|
|
133
112
|
// src/generators/mcp/cline.ts
|
|
134
|
-
function generateClineMcp(config
|
|
113
|
+
function generateClineMcp(config) {
|
|
135
114
|
const clineConfig = {
|
|
136
115
|
mcpServers: {}
|
|
137
116
|
};
|
|
@@ -230,7 +209,7 @@ var init_copilot = __esm({
|
|
|
230
209
|
});
|
|
231
210
|
|
|
232
211
|
// src/generators/mcp/cursor.ts
|
|
233
|
-
function generateCursorMcp(config
|
|
212
|
+
function generateCursorMcp(config) {
|
|
234
213
|
const cursorConfig = {
|
|
235
214
|
mcpServers: {}
|
|
236
215
|
};
|
|
@@ -269,7 +248,7 @@ var init_cursor = __esm({
|
|
|
269
248
|
});
|
|
270
249
|
|
|
271
250
|
// src/generators/mcp/geminicli.ts
|
|
272
|
-
function generateGeminiCliMcp(config
|
|
251
|
+
function generateGeminiCliMcp(config) {
|
|
273
252
|
const geminiSettings = {
|
|
274
253
|
mcpServers: {}
|
|
275
254
|
};
|
|
@@ -314,7 +293,7 @@ var init_geminicli = __esm({
|
|
|
314
293
|
});
|
|
315
294
|
|
|
316
295
|
// src/generators/mcp/roo.ts
|
|
317
|
-
function generateRooMcp(config
|
|
296
|
+
function generateRooMcp(config) {
|
|
318
297
|
const rooConfig = {
|
|
319
298
|
mcpServers: {}
|
|
320
299
|
};
|
|
@@ -370,7 +349,7 @@ var import_commander = require("commander");
|
|
|
370
349
|
|
|
371
350
|
// src/cli/commands/add.ts
|
|
372
351
|
var import_promises = require("fs/promises");
|
|
373
|
-
var
|
|
352
|
+
var path = __toESM(require("path"), 1);
|
|
374
353
|
|
|
375
354
|
// src/utils/config.ts
|
|
376
355
|
function getDefaultConfig() {
|
|
@@ -381,12 +360,11 @@ function getDefaultConfig() {
|
|
|
381
360
|
cursor: ".cursor/rules",
|
|
382
361
|
cline: ".clinerules",
|
|
383
362
|
claudecode: ".",
|
|
384
|
-
claude: ".",
|
|
385
363
|
roo: ".roo/rules",
|
|
386
364
|
geminicli: ".gemini/memories"
|
|
387
365
|
},
|
|
388
366
|
watchEnabled: false,
|
|
389
|
-
defaultTargets: ["copilot", "cursor", "cline", "claudecode", "
|
|
367
|
+
defaultTargets: ["copilot", "cursor", "cline", "claudecode", "roo", "geminicli"]
|
|
390
368
|
};
|
|
391
369
|
}
|
|
392
370
|
function resolveTargets(targets, config) {
|
|
@@ -418,7 +396,7 @@ async function addCommand(filename) {
|
|
|
418
396
|
const config = getDefaultConfig();
|
|
419
397
|
const sanitizedFilename = sanitizeFilename(filename);
|
|
420
398
|
const rulesDir = config.aiRulesDir;
|
|
421
|
-
const filePath =
|
|
399
|
+
const filePath = path.join(rulesDir, `${sanitizedFilename}.md`);
|
|
422
400
|
await (0, import_promises.mkdir)(rulesDir, { recursive: true });
|
|
423
401
|
const template = generateRuleTemplate(sanitizedFilename);
|
|
424
402
|
await (0, import_promises.writeFile)(filePath, template, "utf8");
|
|
@@ -433,15 +411,23 @@ async function addCommand(filename) {
|
|
|
433
411
|
}
|
|
434
412
|
|
|
435
413
|
// src/generators/rules/claudecode.ts
|
|
436
|
-
var
|
|
414
|
+
var import_node_path4 = require("path");
|
|
415
|
+
|
|
416
|
+
// src/types/claudecode.ts
|
|
417
|
+
var import_v4 = require("zod/v4");
|
|
418
|
+
var ClaudeSettingsSchema = import_v4.z.looseObject({
|
|
419
|
+
permissions: import_v4.z.looseObject({
|
|
420
|
+
deny: import_v4.z.array(import_v4.z.string()).default([])
|
|
421
|
+
}).default({ deny: [] })
|
|
422
|
+
});
|
|
437
423
|
|
|
438
424
|
// src/utils/file.ts
|
|
439
425
|
var import_promises3 = require("fs/promises");
|
|
440
|
-
var
|
|
426
|
+
var import_node_path3 = require("path");
|
|
441
427
|
|
|
442
428
|
// src/utils/file-ops.ts
|
|
443
429
|
var import_promises2 = require("fs/promises");
|
|
444
|
-
var
|
|
430
|
+
var import_node_path = require("path");
|
|
445
431
|
async function ensureDir(dirPath) {
|
|
446
432
|
try {
|
|
447
433
|
await (0, import_promises2.stat)(dirPath);
|
|
@@ -453,7 +439,7 @@ async function readFileContent(filepath) {
|
|
|
453
439
|
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
454
440
|
}
|
|
455
441
|
async function writeFileContent(filepath, content) {
|
|
456
|
-
await ensureDir((0,
|
|
442
|
+
await ensureDir((0, import_node_path.dirname)(filepath));
|
|
457
443
|
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
458
444
|
}
|
|
459
445
|
async function fileExists(filepath) {
|
|
@@ -466,14 +452,14 @@ async function fileExists(filepath) {
|
|
|
466
452
|
}
|
|
467
453
|
|
|
468
454
|
// src/utils/ignore.ts
|
|
469
|
-
var
|
|
455
|
+
var import_node_path2 = require("path");
|
|
470
456
|
var import_micromatch = __toESM(require("micromatch"), 1);
|
|
471
457
|
var cachedIgnorePatterns = null;
|
|
472
458
|
async function loadIgnorePatterns(baseDir = process.cwd()) {
|
|
473
459
|
if (cachedIgnorePatterns) {
|
|
474
460
|
return cachedIgnorePatterns;
|
|
475
461
|
}
|
|
476
|
-
const ignorePath = (0,
|
|
462
|
+
const ignorePath = (0, import_node_path2.join)(baseDir, ".rulesyncignore");
|
|
477
463
|
if (!await fileExists(ignorePath)) {
|
|
478
464
|
cachedIgnorePatterns = { patterns: [] };
|
|
479
465
|
return cachedIgnorePatterns;
|
|
@@ -520,7 +506,7 @@ function filterIgnoredFiles(files, ignorePatterns) {
|
|
|
520
506
|
async function findFiles(dir, extension = ".md", ignorePatterns) {
|
|
521
507
|
try {
|
|
522
508
|
const files = await (0, import_promises3.readdir)(dir);
|
|
523
|
-
const filtered = files.filter((file) => file.endsWith(extension)).map((file) => (0,
|
|
509
|
+
const filtered = files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path3.join)(dir, file));
|
|
524
510
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
525
511
|
return filterIgnoredFiles(filtered, ignorePatterns);
|
|
526
512
|
}
|
|
@@ -569,23 +555,23 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
|
569
555
|
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
570
556
|
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
571
557
|
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
572
|
-
const claudeOutputDir = baseDir ? (0,
|
|
558
|
+
const claudeOutputDir = baseDir ? (0, import_node_path4.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
|
|
573
559
|
outputs.push({
|
|
574
560
|
tool: "claudecode",
|
|
575
|
-
filepath: (0,
|
|
561
|
+
filepath: (0, import_node_path4.join)(claudeOutputDir, "CLAUDE.md"),
|
|
576
562
|
content: claudeMdContent
|
|
577
563
|
});
|
|
578
564
|
for (const rule of detailRules) {
|
|
579
565
|
const memoryContent = generateMemoryFile(rule);
|
|
580
566
|
outputs.push({
|
|
581
567
|
tool: "claudecode",
|
|
582
|
-
filepath: (0,
|
|
568
|
+
filepath: (0, import_node_path4.join)(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
|
|
583
569
|
content: memoryContent
|
|
584
570
|
});
|
|
585
571
|
}
|
|
586
572
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
587
573
|
if (ignorePatterns.patterns.length > 0) {
|
|
588
|
-
const settingsPath = baseDir ? (0,
|
|
574
|
+
const settingsPath = baseDir ? (0, import_node_path4.join)(baseDir, ".claude", "settings.json") : (0, import_node_path4.join)(".claude", "settings.json");
|
|
589
575
|
await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
|
|
590
576
|
}
|
|
591
577
|
return outputs;
|
|
@@ -617,51 +603,46 @@ function generateMemoryFile(rule) {
|
|
|
617
603
|
return rule.content.trim();
|
|
618
604
|
}
|
|
619
605
|
async function updateClaudeSettings(settingsPath, ignorePatterns) {
|
|
620
|
-
let
|
|
606
|
+
let rawSettings = {};
|
|
621
607
|
if (await fileExists(settingsPath)) {
|
|
622
608
|
try {
|
|
623
609
|
const content = await readFileContent(settingsPath);
|
|
624
|
-
|
|
610
|
+
rawSettings = JSON.parse(content);
|
|
625
611
|
} catch {
|
|
626
612
|
console.warn(`Failed to parse existing ${settingsPath}, creating new settings`);
|
|
627
|
-
|
|
613
|
+
rawSettings = {};
|
|
628
614
|
}
|
|
629
615
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
settingsObj.permissions = {};
|
|
616
|
+
const parseResult = ClaudeSettingsSchema.safeParse(rawSettings);
|
|
617
|
+
const settings = parseResult.success ? parseResult.data : ClaudeSettingsSchema.parse({});
|
|
618
|
+
const readDenyRules = ignorePatterns.map((pattern) => `Read(${pattern})`);
|
|
619
|
+
if (!settings.permissions) {
|
|
620
|
+
settings.permissions = { deny: [] };
|
|
636
621
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
permissions.deny = [];
|
|
622
|
+
if (!Array.isArray(settings.permissions.deny)) {
|
|
623
|
+
settings.permissions.deny = [];
|
|
640
624
|
}
|
|
641
|
-
const
|
|
642
|
-
const denyArray = permissions.deny;
|
|
643
|
-
const filteredDeny = denyArray.filter((rule) => {
|
|
644
|
-
if (typeof rule !== "string") return false;
|
|
625
|
+
const filteredDeny = settings.permissions.deny.filter((rule) => {
|
|
645
626
|
if (!rule.startsWith("Read(")) return true;
|
|
646
627
|
const match = rule.match(/^Read\((.*)\)$/);
|
|
647
628
|
if (!match) return true;
|
|
648
629
|
return !ignorePatterns.includes(match[1] ?? "");
|
|
649
630
|
});
|
|
650
631
|
filteredDeny.push(...readDenyRules);
|
|
651
|
-
permissions.deny =
|
|
652
|
-
const jsonContent = JSON.stringify(
|
|
632
|
+
settings.permissions.deny = Array.from(new Set(filteredDeny));
|
|
633
|
+
const jsonContent = JSON.stringify(settings, null, 2);
|
|
653
634
|
await writeFileContent(settingsPath, jsonContent);
|
|
654
635
|
console.log(`\u2705 Updated Claude Code settings: ${settingsPath}`);
|
|
655
636
|
}
|
|
656
637
|
|
|
657
638
|
// src/generators/rules/cline.ts
|
|
658
|
-
var
|
|
639
|
+
var import_node_path5 = require("path");
|
|
659
640
|
async function generateClineConfig(rules, config, baseDir) {
|
|
660
641
|
const outputs = [];
|
|
661
642
|
for (const rule of rules) {
|
|
662
643
|
const content = generateClineMarkdown(rule);
|
|
663
|
-
const outputDir = baseDir ? (0,
|
|
664
|
-
const filepath = (0,
|
|
644
|
+
const outputDir = baseDir ? (0, import_node_path5.join)(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
|
|
645
|
+
const filepath = (0, import_node_path5.join)(outputDir, `${rule.filename}.md`);
|
|
665
646
|
outputs.push({
|
|
666
647
|
tool: "cline",
|
|
667
648
|
filepath,
|
|
@@ -670,7 +651,7 @@ async function generateClineConfig(rules, config, baseDir) {
|
|
|
670
651
|
}
|
|
671
652
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
672
653
|
if (ignorePatterns.patterns.length > 0) {
|
|
673
|
-
const clineIgnorePath = baseDir ? (0,
|
|
654
|
+
const clineIgnorePath = baseDir ? (0, import_node_path5.join)(baseDir, ".clineignore") : ".clineignore";
|
|
674
655
|
const clineIgnoreContent = generateClineIgnore(ignorePatterns.patterns);
|
|
675
656
|
outputs.push({
|
|
676
657
|
tool: "cline",
|
|
@@ -694,14 +675,14 @@ function generateClineIgnore(patterns) {
|
|
|
694
675
|
}
|
|
695
676
|
|
|
696
677
|
// src/generators/rules/copilot.ts
|
|
697
|
-
var
|
|
678
|
+
var import_node_path6 = require("path");
|
|
698
679
|
async function generateCopilotConfig(rules, config, baseDir) {
|
|
699
680
|
const outputs = [];
|
|
700
681
|
for (const rule of rules) {
|
|
701
682
|
const content = generateCopilotMarkdown(rule);
|
|
702
683
|
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
703
|
-
const outputDir = baseDir ? (0,
|
|
704
|
-
const filepath = (0,
|
|
684
|
+
const outputDir = baseDir ? (0, import_node_path6.join)(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
|
|
685
|
+
const filepath = (0, import_node_path6.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
705
686
|
outputs.push({
|
|
706
687
|
tool: "copilot",
|
|
707
688
|
filepath,
|
|
@@ -710,7 +691,7 @@ async function generateCopilotConfig(rules, config, baseDir) {
|
|
|
710
691
|
}
|
|
711
692
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
712
693
|
if (ignorePatterns.patterns.length > 0) {
|
|
713
|
-
const copilotIgnorePath = baseDir ? (0,
|
|
694
|
+
const copilotIgnorePath = baseDir ? (0, import_node_path6.join)(baseDir, ".copilotignore") : ".copilotignore";
|
|
714
695
|
const copilotIgnoreContent = generateCopilotIgnore(ignorePatterns.patterns);
|
|
715
696
|
outputs.push({
|
|
716
697
|
tool: "copilot",
|
|
@@ -746,13 +727,13 @@ function generateCopilotIgnore(patterns) {
|
|
|
746
727
|
}
|
|
747
728
|
|
|
748
729
|
// src/generators/rules/cursor.ts
|
|
749
|
-
var
|
|
730
|
+
var import_node_path7 = require("path");
|
|
750
731
|
async function generateCursorConfig(rules, config, baseDir) {
|
|
751
732
|
const outputs = [];
|
|
752
733
|
for (const rule of rules) {
|
|
753
734
|
const content = generateCursorMarkdown(rule);
|
|
754
|
-
const outputDir = baseDir ? (0,
|
|
755
|
-
const filepath = (0,
|
|
735
|
+
const outputDir = baseDir ? (0, import_node_path7.join)(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
|
|
736
|
+
const filepath = (0, import_node_path7.join)(outputDir, `${rule.filename}.mdc`);
|
|
756
737
|
outputs.push({
|
|
757
738
|
tool: "cursor",
|
|
758
739
|
filepath,
|
|
@@ -761,7 +742,7 @@ async function generateCursorConfig(rules, config, baseDir) {
|
|
|
761
742
|
}
|
|
762
743
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
763
744
|
if (ignorePatterns.patterns.length > 0) {
|
|
764
|
-
const cursorIgnorePath = baseDir ? (0,
|
|
745
|
+
const cursorIgnorePath = baseDir ? (0, import_node_path7.join)(baseDir, ".cursorignore") : ".cursorignore";
|
|
765
746
|
const cursorIgnoreContent = generateCursorIgnore(ignorePatterns.patterns);
|
|
766
747
|
outputs.push({
|
|
767
748
|
tool: "cursor",
|
|
@@ -834,15 +815,15 @@ function generateCursorIgnore(patterns) {
|
|
|
834
815
|
}
|
|
835
816
|
|
|
836
817
|
// src/generators/rules/geminicli.ts
|
|
837
|
-
var
|
|
818
|
+
var import_node_path8 = require("path");
|
|
838
819
|
async function generateGeminiConfig(rules, config, baseDir) {
|
|
839
820
|
const outputs = [];
|
|
840
821
|
const rootRule = rules.find((rule) => rule.frontmatter.root === true);
|
|
841
822
|
const memoryRules = rules.filter((rule) => rule.frontmatter.root === false);
|
|
842
823
|
for (const rule of memoryRules) {
|
|
843
824
|
const content = generateGeminiMemoryMarkdown(rule);
|
|
844
|
-
const outputDir = baseDir ? (0,
|
|
845
|
-
const filepath = (0,
|
|
825
|
+
const outputDir = baseDir ? (0, import_node_path8.join)(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
|
|
826
|
+
const filepath = (0, import_node_path8.join)(outputDir, `${rule.filename}.md`);
|
|
846
827
|
outputs.push({
|
|
847
828
|
tool: "geminicli",
|
|
848
829
|
filepath,
|
|
@@ -850,7 +831,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
|
|
|
850
831
|
});
|
|
851
832
|
}
|
|
852
833
|
const rootContent = generateGeminiRootMarkdown(rootRule, memoryRules, baseDir);
|
|
853
|
-
const rootFilepath = baseDir ? (0,
|
|
834
|
+
const rootFilepath = baseDir ? (0, import_node_path8.join)(baseDir, "GEMINI.md") : "GEMINI.md";
|
|
854
835
|
outputs.push({
|
|
855
836
|
tool: "geminicli",
|
|
856
837
|
filepath: rootFilepath,
|
|
@@ -858,7 +839,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
|
|
|
858
839
|
});
|
|
859
840
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
860
841
|
if (ignorePatterns.patterns.length > 0) {
|
|
861
|
-
const aiexcludePath = baseDir ? (0,
|
|
842
|
+
const aiexcludePath = baseDir ? (0, import_node_path8.join)(baseDir, ".aiexclude") : ".aiexclude";
|
|
862
843
|
const aiexcludeContent = generateAiexclude(ignorePatterns.patterns);
|
|
863
844
|
outputs.push({
|
|
864
845
|
tool: "geminicli",
|
|
@@ -906,13 +887,13 @@ function generateAiexclude(patterns) {
|
|
|
906
887
|
}
|
|
907
888
|
|
|
908
889
|
// src/generators/rules/roo.ts
|
|
909
|
-
var
|
|
890
|
+
var import_node_path9 = require("path");
|
|
910
891
|
async function generateRooConfig(rules, config, baseDir) {
|
|
911
892
|
const outputs = [];
|
|
912
893
|
for (const rule of rules) {
|
|
913
894
|
const content = generateRooMarkdown(rule);
|
|
914
|
-
const outputDir = baseDir ? (0,
|
|
915
|
-
const filepath = (0,
|
|
895
|
+
const outputDir = baseDir ? (0, import_node_path9.join)(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
|
|
896
|
+
const filepath = (0, import_node_path9.join)(outputDir, `${rule.filename}.md`);
|
|
916
897
|
outputs.push({
|
|
917
898
|
tool: "roo",
|
|
918
899
|
filepath,
|
|
@@ -921,7 +902,7 @@ async function generateRooConfig(rules, config, baseDir) {
|
|
|
921
902
|
}
|
|
922
903
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
923
904
|
if (ignorePatterns.patterns.length > 0) {
|
|
924
|
-
const rooIgnorePath = baseDir ? (0,
|
|
905
|
+
const rooIgnorePath = baseDir ? (0, import_node_path9.join)(baseDir, ".rooignore") : ".rooignore";
|
|
925
906
|
const rooIgnoreContent = generateRooIgnore(ignorePatterns.patterns);
|
|
926
907
|
outputs.push({
|
|
927
908
|
tool: "roo",
|
|
@@ -994,7 +975,7 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
994
975
|
}
|
|
995
976
|
|
|
996
977
|
// src/core/parser.ts
|
|
997
|
-
var
|
|
978
|
+
var import_node_path10 = require("path");
|
|
998
979
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
999
980
|
async function parseRulesFromDirectory(aiRulesDir) {
|
|
1000
981
|
const ignorePatterns = await loadIgnorePatterns();
|
|
@@ -1031,7 +1012,7 @@ async function parseRuleFile(filepath) {
|
|
|
1031
1012
|
const parsed = (0, import_gray_matter.default)(content);
|
|
1032
1013
|
validateFrontmatter(parsed.data, filepath);
|
|
1033
1014
|
const frontmatter = parsed.data;
|
|
1034
|
-
const filename = (0,
|
|
1015
|
+
const filename = (0, import_node_path10.basename)(filepath, ".md");
|
|
1035
1016
|
return {
|
|
1036
1017
|
frontmatter,
|
|
1037
1018
|
content: parsed.content,
|
|
@@ -1160,11 +1141,10 @@ async function validateRule(rule) {
|
|
|
1160
1141
|
}
|
|
1161
1142
|
|
|
1162
1143
|
// src/core/mcp-generator.ts
|
|
1163
|
-
var
|
|
1164
|
-
var import_node_path13 = __toESM(require("path"), 1);
|
|
1144
|
+
var path3 = __toESM(require("path"), 1);
|
|
1165
1145
|
|
|
1166
1146
|
// src/generators/mcp/index.ts
|
|
1167
|
-
|
|
1147
|
+
init_claudecode();
|
|
1168
1148
|
init_cline();
|
|
1169
1149
|
init_copilot();
|
|
1170
1150
|
init_cursor();
|
|
@@ -1172,15 +1152,15 @@ init_geminicli();
|
|
|
1172
1152
|
init_roo();
|
|
1173
1153
|
|
|
1174
1154
|
// src/core/mcp-parser.ts
|
|
1175
|
-
var
|
|
1176
|
-
var
|
|
1155
|
+
var fs = __toESM(require("fs"), 1);
|
|
1156
|
+
var path2 = __toESM(require("path"), 1);
|
|
1177
1157
|
function parseMcpConfig(projectRoot) {
|
|
1178
|
-
const mcpPath =
|
|
1179
|
-
if (!
|
|
1158
|
+
const mcpPath = path2.join(projectRoot, ".rulesync", ".mcp.json");
|
|
1159
|
+
if (!fs.existsSync(mcpPath)) {
|
|
1180
1160
|
return null;
|
|
1181
1161
|
}
|
|
1182
1162
|
try {
|
|
1183
|
-
const content =
|
|
1163
|
+
const content = fs.readFileSync(mcpPath, "utf-8");
|
|
1184
1164
|
const rawConfig = JSON.parse(content);
|
|
1185
1165
|
if (rawConfig.servers && !rawConfig.mcpServers) {
|
|
1186
1166
|
rawConfig.mcpServers = rawConfig.servers;
|
|
@@ -1211,54 +1191,35 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
1211
1191
|
const generators = [
|
|
1212
1192
|
{
|
|
1213
1193
|
tool: "claude-project",
|
|
1214
|
-
path:
|
|
1215
|
-
generate: () => generateClaudeMcp(config
|
|
1194
|
+
path: path3.join(targetRoot, ".mcp.json"),
|
|
1195
|
+
generate: () => generateClaudeMcp(config)
|
|
1216
1196
|
},
|
|
1217
1197
|
{
|
|
1218
1198
|
tool: "copilot-editor",
|
|
1219
|
-
path:
|
|
1199
|
+
path: path3.join(targetRoot, ".vscode", "mcp.json"),
|
|
1220
1200
|
generate: () => generateCopilotMcp(config, "editor")
|
|
1221
1201
|
},
|
|
1222
1202
|
{
|
|
1223
1203
|
tool: "cursor-project",
|
|
1224
|
-
path:
|
|
1225
|
-
generate: () => generateCursorMcp(config
|
|
1204
|
+
path: path3.join(targetRoot, ".cursor", "mcp.json"),
|
|
1205
|
+
generate: () => generateCursorMcp(config)
|
|
1226
1206
|
},
|
|
1227
1207
|
{
|
|
1228
1208
|
tool: "cline-project",
|
|
1229
|
-
path:
|
|
1230
|
-
generate: () => generateClineMcp(config
|
|
1209
|
+
path: path3.join(targetRoot, ".cline", "mcp.json"),
|
|
1210
|
+
generate: () => generateClineMcp(config)
|
|
1231
1211
|
},
|
|
1232
1212
|
{
|
|
1233
1213
|
tool: "gemini-project",
|
|
1234
|
-
path:
|
|
1235
|
-
generate: () => generateGeminiCliMcp(config
|
|
1214
|
+
path: path3.join(targetRoot, ".gemini", "settings.json"),
|
|
1215
|
+
generate: () => generateGeminiCliMcp(config)
|
|
1236
1216
|
},
|
|
1237
1217
|
{
|
|
1238
1218
|
tool: "roo-project",
|
|
1239
|
-
path:
|
|
1240
|
-
generate: () => generateRooMcp(config
|
|
1219
|
+
path: path3.join(targetRoot, ".roo", "mcp.json"),
|
|
1220
|
+
generate: () => generateRooMcp(config)
|
|
1241
1221
|
}
|
|
1242
1222
|
];
|
|
1243
|
-
if (!baseDir) {
|
|
1244
|
-
generators.push(
|
|
1245
|
-
{
|
|
1246
|
-
tool: "claude-global",
|
|
1247
|
-
path: import_node_path13.default.join(import_node_os.default.homedir(), ".claude", "settings.json"),
|
|
1248
|
-
generate: () => generateClaudeMcp(config, "global")
|
|
1249
|
-
},
|
|
1250
|
-
{
|
|
1251
|
-
tool: "cursor-global",
|
|
1252
|
-
path: import_node_path13.default.join(import_node_os.default.homedir(), ".cursor", "mcp.json"),
|
|
1253
|
-
generate: () => generateCursorMcp(config, "global")
|
|
1254
|
-
},
|
|
1255
|
-
{
|
|
1256
|
-
tool: "gemini-global",
|
|
1257
|
-
path: import_node_path13.default.join(import_node_os.default.homedir(), ".gemini", "settings.json"),
|
|
1258
|
-
generate: () => generateGeminiCliMcp(config, "global")
|
|
1259
|
-
}
|
|
1260
|
-
);
|
|
1261
|
-
}
|
|
1262
1223
|
for (const generator of generators) {
|
|
1263
1224
|
try {
|
|
1264
1225
|
const content = generator.generate();
|
|
@@ -1412,10 +1373,10 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1412
1373
|
}
|
|
1413
1374
|
|
|
1414
1375
|
// src/cli/commands/gitignore.ts
|
|
1415
|
-
var
|
|
1416
|
-
var
|
|
1376
|
+
var import_node_fs = require("fs");
|
|
1377
|
+
var import_node_path11 = require("path");
|
|
1417
1378
|
var gitignoreCommand = async () => {
|
|
1418
|
-
const gitignorePath = (0,
|
|
1379
|
+
const gitignorePath = (0, import_node_path11.join)(process.cwd(), ".gitignore");
|
|
1419
1380
|
const rulesFilesToIgnore = [
|
|
1420
1381
|
"# Generated by rulesync - AI tool configuration files",
|
|
1421
1382
|
"**/.github/copilot-instructions.md",
|
|
@@ -1441,8 +1402,8 @@ var gitignoreCommand = async () => {
|
|
|
1441
1402
|
"**/.roo/mcp.json"
|
|
1442
1403
|
];
|
|
1443
1404
|
let gitignoreContent = "";
|
|
1444
|
-
if ((0,
|
|
1445
|
-
gitignoreContent = (0,
|
|
1405
|
+
if ((0, import_node_fs.existsSync)(gitignorePath)) {
|
|
1406
|
+
gitignoreContent = (0, import_node_fs.readFileSync)(gitignorePath, "utf-8");
|
|
1446
1407
|
}
|
|
1447
1408
|
const linesToAdd = [];
|
|
1448
1409
|
for (const rule of rulesFilesToIgnore) {
|
|
@@ -1459,7 +1420,7 @@ var gitignoreCommand = async () => {
|
|
|
1459
1420
|
${linesToAdd.join("\n")}
|
|
1460
1421
|
` : `${linesToAdd.join("\n")}
|
|
1461
1422
|
`;
|
|
1462
|
-
(0,
|
|
1423
|
+
(0, import_node_fs.writeFileSync)(gitignorePath, newContent);
|
|
1463
1424
|
console.log(`\u2705 Added ${linesToAdd.length} rules to .gitignore:`);
|
|
1464
1425
|
for (const line of linesToAdd) {
|
|
1465
1426
|
if (!line.startsWith("#")) {
|
|
@@ -1469,17 +1430,17 @@ ${linesToAdd.join("\n")}
|
|
|
1469
1430
|
};
|
|
1470
1431
|
|
|
1471
1432
|
// src/core/importer.ts
|
|
1472
|
-
var
|
|
1433
|
+
var import_node_path18 = require("path");
|
|
1473
1434
|
var import_gray_matter4 = __toESM(require("gray-matter"), 1);
|
|
1474
1435
|
|
|
1475
1436
|
// src/parsers/claudecode.ts
|
|
1476
|
-
var
|
|
1437
|
+
var import_node_path12 = require("path");
|
|
1477
1438
|
async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
1478
1439
|
const errors = [];
|
|
1479
1440
|
const rules = [];
|
|
1480
1441
|
let ignorePatterns;
|
|
1481
1442
|
let mcpServers;
|
|
1482
|
-
const claudeFilePath = (0,
|
|
1443
|
+
const claudeFilePath = (0, import_node_path12.join)(baseDir, "CLAUDE.md");
|
|
1483
1444
|
if (!await fileExists(claudeFilePath)) {
|
|
1484
1445
|
errors.push("CLAUDE.md file not found");
|
|
1485
1446
|
return { rules, errors };
|
|
@@ -1490,12 +1451,12 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
|
1490
1451
|
if (mainRule) {
|
|
1491
1452
|
rules.push(mainRule);
|
|
1492
1453
|
}
|
|
1493
|
-
const memoryDir = (0,
|
|
1454
|
+
const memoryDir = (0, import_node_path12.join)(baseDir, ".claude", "memories");
|
|
1494
1455
|
if (await fileExists(memoryDir)) {
|
|
1495
1456
|
const memoryRules = await parseClaudeMemoryFiles(memoryDir);
|
|
1496
1457
|
rules.push(...memoryRules);
|
|
1497
1458
|
}
|
|
1498
|
-
const settingsPath = (0,
|
|
1459
|
+
const settingsPath = (0, import_node_path12.join)(baseDir, ".claude", "settings.json");
|
|
1499
1460
|
if (await fileExists(settingsPath)) {
|
|
1500
1461
|
const settingsResult = await parseClaudeSettings(settingsPath);
|
|
1501
1462
|
if (settingsResult.ignorePatterns) {
|
|
@@ -1552,10 +1513,10 @@ async function parseClaudeMemoryFiles(memoryDir) {
|
|
|
1552
1513
|
const files = await readdir2(memoryDir);
|
|
1553
1514
|
for (const file of files) {
|
|
1554
1515
|
if (file.endsWith(".md")) {
|
|
1555
|
-
const filePath = (0,
|
|
1516
|
+
const filePath = (0, import_node_path12.join)(memoryDir, file);
|
|
1556
1517
|
const content = await readFileContent(filePath);
|
|
1557
1518
|
if (content.trim()) {
|
|
1558
|
-
const filename = (0,
|
|
1519
|
+
const filename = (0, import_node_path12.basename)(file, ".md");
|
|
1559
1520
|
const frontmatter = {
|
|
1560
1521
|
root: false,
|
|
1561
1522
|
targets: ["claudecode"],
|
|
@@ -1614,11 +1575,11 @@ async function parseClaudeSettings(settingsPath) {
|
|
|
1614
1575
|
}
|
|
1615
1576
|
|
|
1616
1577
|
// src/parsers/cline.ts
|
|
1617
|
-
var
|
|
1578
|
+
var import_node_path13 = require("path");
|
|
1618
1579
|
async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
1619
1580
|
const errors = [];
|
|
1620
1581
|
const rules = [];
|
|
1621
|
-
const clineFilePath = (0,
|
|
1582
|
+
const clineFilePath = (0, import_node_path13.join)(baseDir, ".cline", "instructions.md");
|
|
1622
1583
|
if (await fileExists(clineFilePath)) {
|
|
1623
1584
|
try {
|
|
1624
1585
|
const content = await readFileContent(clineFilePath);
|
|
@@ -1641,14 +1602,14 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
1641
1602
|
errors.push(`Failed to parse .cline/instructions.md: ${errorMessage}`);
|
|
1642
1603
|
}
|
|
1643
1604
|
}
|
|
1644
|
-
const clinerulesDirPath = (0,
|
|
1605
|
+
const clinerulesDirPath = (0, import_node_path13.join)(baseDir, ".clinerules");
|
|
1645
1606
|
if (await fileExists(clinerulesDirPath)) {
|
|
1646
1607
|
try {
|
|
1647
1608
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1648
1609
|
const files = await readdir2(clinerulesDirPath);
|
|
1649
1610
|
for (const file of files) {
|
|
1650
1611
|
if (file.endsWith(".md")) {
|
|
1651
|
-
const filePath = (0,
|
|
1612
|
+
const filePath = (0, import_node_path13.join)(clinerulesDirPath, file);
|
|
1652
1613
|
try {
|
|
1653
1614
|
const content = await readFileContent(filePath);
|
|
1654
1615
|
if (content.trim()) {
|
|
@@ -1684,12 +1645,12 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
1684
1645
|
}
|
|
1685
1646
|
|
|
1686
1647
|
// src/parsers/copilot.ts
|
|
1687
|
-
var
|
|
1648
|
+
var import_node_path14 = require("path");
|
|
1688
1649
|
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
1689
1650
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
1690
1651
|
const errors = [];
|
|
1691
1652
|
const rules = [];
|
|
1692
|
-
const copilotFilePath = (0,
|
|
1653
|
+
const copilotFilePath = (0, import_node_path14.join)(baseDir, ".github", "copilot-instructions.md");
|
|
1693
1654
|
if (await fileExists(copilotFilePath)) {
|
|
1694
1655
|
try {
|
|
1695
1656
|
const rawContent = await readFileContent(copilotFilePath);
|
|
@@ -1714,19 +1675,19 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
1714
1675
|
errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
|
|
1715
1676
|
}
|
|
1716
1677
|
}
|
|
1717
|
-
const instructionsDir = (0,
|
|
1678
|
+
const instructionsDir = (0, import_node_path14.join)(baseDir, ".github", "instructions");
|
|
1718
1679
|
if (await fileExists(instructionsDir)) {
|
|
1719
1680
|
try {
|
|
1720
1681
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1721
1682
|
const files = await readdir2(instructionsDir);
|
|
1722
1683
|
for (const file of files) {
|
|
1723
1684
|
if (file.endsWith(".instructions.md")) {
|
|
1724
|
-
const filePath = (0,
|
|
1685
|
+
const filePath = (0, import_node_path14.join)(instructionsDir, file);
|
|
1725
1686
|
const rawContent = await readFileContent(filePath);
|
|
1726
1687
|
const parsed = (0, import_gray_matter2.default)(rawContent);
|
|
1727
1688
|
const content = parsed.content.trim();
|
|
1728
1689
|
if (content) {
|
|
1729
|
-
const filename = (0,
|
|
1690
|
+
const filename = (0, import_node_path14.basename)(file, ".instructions.md");
|
|
1730
1691
|
const frontmatter = {
|
|
1731
1692
|
root: false,
|
|
1732
1693
|
targets: ["copilot"],
|
|
@@ -1756,7 +1717,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
1756
1717
|
}
|
|
1757
1718
|
|
|
1758
1719
|
// src/parsers/cursor.ts
|
|
1759
|
-
var
|
|
1720
|
+
var import_node_path15 = require("path");
|
|
1760
1721
|
var import_gray_matter3 = __toESM(require("gray-matter"), 1);
|
|
1761
1722
|
var import_js_yaml = require("js-yaml");
|
|
1762
1723
|
var customMatterOptions = {
|
|
@@ -1861,7 +1822,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1861
1822
|
const rules = [];
|
|
1862
1823
|
let ignorePatterns;
|
|
1863
1824
|
let mcpServers;
|
|
1864
|
-
const cursorFilePath = (0,
|
|
1825
|
+
const cursorFilePath = (0, import_node_path15.join)(baseDir, ".cursorrules");
|
|
1865
1826
|
if (await fileExists(cursorFilePath)) {
|
|
1866
1827
|
try {
|
|
1867
1828
|
const rawContent = await readFileContent(cursorFilePath);
|
|
@@ -1882,20 +1843,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1882
1843
|
errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
|
|
1883
1844
|
}
|
|
1884
1845
|
}
|
|
1885
|
-
const cursorRulesDir = (0,
|
|
1846
|
+
const cursorRulesDir = (0, import_node_path15.join)(baseDir, ".cursor", "rules");
|
|
1886
1847
|
if (await fileExists(cursorRulesDir)) {
|
|
1887
1848
|
try {
|
|
1888
1849
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1889
1850
|
const files = await readdir2(cursorRulesDir);
|
|
1890
1851
|
for (const file of files) {
|
|
1891
1852
|
if (file.endsWith(".mdc")) {
|
|
1892
|
-
const filePath = (0,
|
|
1853
|
+
const filePath = (0, import_node_path15.join)(cursorRulesDir, file);
|
|
1893
1854
|
try {
|
|
1894
1855
|
const rawContent = await readFileContent(filePath);
|
|
1895
1856
|
const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
|
|
1896
1857
|
const content = parsed.content.trim();
|
|
1897
1858
|
if (content) {
|
|
1898
|
-
const filename = (0,
|
|
1859
|
+
const filename = (0, import_node_path15.basename)(file, ".mdc");
|
|
1899
1860
|
const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
|
|
1900
1861
|
rules.push({
|
|
1901
1862
|
frontmatter,
|
|
@@ -1918,7 +1879,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1918
1879
|
if (rules.length === 0) {
|
|
1919
1880
|
errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
|
|
1920
1881
|
}
|
|
1921
|
-
const cursorIgnorePath = (0,
|
|
1882
|
+
const cursorIgnorePath = (0, import_node_path15.join)(baseDir, ".cursorignore");
|
|
1922
1883
|
if (await fileExists(cursorIgnorePath)) {
|
|
1923
1884
|
try {
|
|
1924
1885
|
const content = await readFileContent(cursorIgnorePath);
|
|
@@ -1931,7 +1892,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1931
1892
|
errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
|
|
1932
1893
|
}
|
|
1933
1894
|
}
|
|
1934
|
-
const cursorMcpPath = (0,
|
|
1895
|
+
const cursorMcpPath = (0, import_node_path15.join)(baseDir, ".cursor", "mcp.json");
|
|
1935
1896
|
if (await fileExists(cursorMcpPath)) {
|
|
1936
1897
|
try {
|
|
1937
1898
|
const content = await readFileContent(cursorMcpPath);
|
|
@@ -1953,13 +1914,13 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
1953
1914
|
}
|
|
1954
1915
|
|
|
1955
1916
|
// src/parsers/geminicli.ts
|
|
1956
|
-
var
|
|
1917
|
+
var import_node_path16 = require("path");
|
|
1957
1918
|
async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
1958
1919
|
const errors = [];
|
|
1959
1920
|
const rules = [];
|
|
1960
1921
|
let ignorePatterns;
|
|
1961
1922
|
let mcpServers;
|
|
1962
|
-
const geminiFilePath = (0,
|
|
1923
|
+
const geminiFilePath = (0, import_node_path16.join)(baseDir, "GEMINI.md");
|
|
1963
1924
|
if (!await fileExists(geminiFilePath)) {
|
|
1964
1925
|
errors.push("GEMINI.md file not found");
|
|
1965
1926
|
return { rules, errors };
|
|
@@ -1970,12 +1931,12 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
1970
1931
|
if (mainRule) {
|
|
1971
1932
|
rules.push(mainRule);
|
|
1972
1933
|
}
|
|
1973
|
-
const memoryDir = (0,
|
|
1934
|
+
const memoryDir = (0, import_node_path16.join)(baseDir, ".gemini", "memories");
|
|
1974
1935
|
if (await fileExists(memoryDir)) {
|
|
1975
1936
|
const memoryRules = await parseGeminiMemoryFiles(memoryDir);
|
|
1976
1937
|
rules.push(...memoryRules);
|
|
1977
1938
|
}
|
|
1978
|
-
const settingsPath = (0,
|
|
1939
|
+
const settingsPath = (0, import_node_path16.join)(baseDir, ".gemini", "settings.json");
|
|
1979
1940
|
if (await fileExists(settingsPath)) {
|
|
1980
1941
|
const settingsResult = await parseGeminiSettings(settingsPath);
|
|
1981
1942
|
if (settingsResult.ignorePatterns) {
|
|
@@ -1986,7 +1947,7 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
1986
1947
|
}
|
|
1987
1948
|
errors.push(...settingsResult.errors);
|
|
1988
1949
|
}
|
|
1989
|
-
const aiexcludePath = (0,
|
|
1950
|
+
const aiexcludePath = (0, import_node_path16.join)(baseDir, ".aiexclude");
|
|
1990
1951
|
if (await fileExists(aiexcludePath)) {
|
|
1991
1952
|
const aiexcludePatterns = await parseAiexclude(aiexcludePath);
|
|
1992
1953
|
if (aiexcludePatterns.length > 0) {
|
|
@@ -2039,10 +2000,10 @@ async function parseGeminiMemoryFiles(memoryDir) {
|
|
|
2039
2000
|
const files = await readdir2(memoryDir);
|
|
2040
2001
|
for (const file of files) {
|
|
2041
2002
|
if (file.endsWith(".md")) {
|
|
2042
|
-
const filePath = (0,
|
|
2003
|
+
const filePath = (0, import_node_path16.join)(memoryDir, file);
|
|
2043
2004
|
const content = await readFileContent(filePath);
|
|
2044
2005
|
if (content.trim()) {
|
|
2045
|
-
const filename = (0,
|
|
2006
|
+
const filename = (0, import_node_path16.basename)(file, ".md");
|
|
2046
2007
|
const frontmatter = {
|
|
2047
2008
|
root: false,
|
|
2048
2009
|
targets: ["geminicli"],
|
|
@@ -2091,11 +2052,11 @@ async function parseAiexclude(aiexcludePath) {
|
|
|
2091
2052
|
}
|
|
2092
2053
|
|
|
2093
2054
|
// src/parsers/roo.ts
|
|
2094
|
-
var
|
|
2055
|
+
var import_node_path17 = require("path");
|
|
2095
2056
|
async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
2096
2057
|
const errors = [];
|
|
2097
2058
|
const rules = [];
|
|
2098
|
-
const rooFilePath = (0,
|
|
2059
|
+
const rooFilePath = (0, import_node_path17.join)(baseDir, ".roo", "instructions.md");
|
|
2099
2060
|
if (await fileExists(rooFilePath)) {
|
|
2100
2061
|
try {
|
|
2101
2062
|
const content = await readFileContent(rooFilePath);
|
|
@@ -2118,14 +2079,14 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
|
2118
2079
|
errors.push(`Failed to parse .roo/instructions.md: ${errorMessage}`);
|
|
2119
2080
|
}
|
|
2120
2081
|
}
|
|
2121
|
-
const rooRulesDir = (0,
|
|
2082
|
+
const rooRulesDir = (0, import_node_path17.join)(baseDir, ".roo", "rules");
|
|
2122
2083
|
if (await fileExists(rooRulesDir)) {
|
|
2123
2084
|
try {
|
|
2124
2085
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
2125
2086
|
const files = await readdir2(rooRulesDir);
|
|
2126
2087
|
for (const file of files) {
|
|
2127
2088
|
if (file.endsWith(".md")) {
|
|
2128
|
-
const filePath = (0,
|
|
2089
|
+
const filePath = (0, import_node_path17.join)(rooRulesDir, file);
|
|
2129
2090
|
try {
|
|
2130
2091
|
const content = await readFileContent(filePath);
|
|
2131
2092
|
if (content.trim()) {
|
|
@@ -2226,7 +2187,7 @@ async function importConfiguration(options) {
|
|
|
2226
2187
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
2227
2188
|
return { success: false, rulesCreated: 0, errors };
|
|
2228
2189
|
}
|
|
2229
|
-
const rulesDirPath = (0,
|
|
2190
|
+
const rulesDirPath = (0, import_node_path18.join)(baseDir, rulesDir);
|
|
2230
2191
|
try {
|
|
2231
2192
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
2232
2193
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -2240,7 +2201,7 @@ async function importConfiguration(options) {
|
|
|
2240
2201
|
try {
|
|
2241
2202
|
const baseFilename = `${tool}__${rule.filename}`;
|
|
2242
2203
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
2243
|
-
const filePath = (0,
|
|
2204
|
+
const filePath = (0, import_node_path18.join)(rulesDirPath, `${filename}.md`);
|
|
2244
2205
|
const content = generateRuleFileContent(rule);
|
|
2245
2206
|
await writeFileContent(filePath, content);
|
|
2246
2207
|
rulesCreated++;
|
|
@@ -2255,7 +2216,7 @@ async function importConfiguration(options) {
|
|
|
2255
2216
|
let ignoreFileCreated = false;
|
|
2256
2217
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
2257
2218
|
try {
|
|
2258
|
-
const rulesyncignorePath = (0,
|
|
2219
|
+
const rulesyncignorePath = (0, import_node_path18.join)(baseDir, ".rulesyncignore");
|
|
2259
2220
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
2260
2221
|
`;
|
|
2261
2222
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -2271,7 +2232,7 @@ async function importConfiguration(options) {
|
|
|
2271
2232
|
let mcpFileCreated = false;
|
|
2272
2233
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
2273
2234
|
try {
|
|
2274
|
-
const mcpPath = (0,
|
|
2235
|
+
const mcpPath = (0, import_node_path18.join)(baseDir, rulesDir, ".mcp.json");
|
|
2275
2236
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
2276
2237
|
`;
|
|
2277
2238
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -2299,7 +2260,7 @@ function generateRuleFileContent(rule) {
|
|
|
2299
2260
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
2300
2261
|
let filename = baseFilename;
|
|
2301
2262
|
let counter = 1;
|
|
2302
|
-
while (await fileExists((0,
|
|
2263
|
+
while (await fileExists((0, import_node_path18.join)(rulesDir, `${filename}.md`))) {
|
|
2303
2264
|
filename = `${baseFilename}-${counter}`;
|
|
2304
2265
|
counter++;
|
|
2305
2266
|
}
|
|
@@ -2364,7 +2325,7 @@ async function importCommand(options = {}) {
|
|
|
2364
2325
|
}
|
|
2365
2326
|
|
|
2366
2327
|
// src/cli/commands/init.ts
|
|
2367
|
-
var
|
|
2328
|
+
var import_node_path19 = require("path");
|
|
2368
2329
|
async function initCommand() {
|
|
2369
2330
|
const aiRulesDir = ".rulesync";
|
|
2370
2331
|
console.log("Initializing rulesync...");
|
|
@@ -2494,7 +2455,7 @@ globs: ["src/api/**/*.ts", "src/services/**/*.ts", "src/models/**/*.ts"]
|
|
|
2494
2455
|
}
|
|
2495
2456
|
];
|
|
2496
2457
|
for (const file of sampleFiles) {
|
|
2497
|
-
const filepath = (0,
|
|
2458
|
+
const filepath = (0, import_node_path19.join)(aiRulesDir, file.filename);
|
|
2498
2459
|
if (!await fileExists(filepath)) {
|
|
2499
2460
|
await writeFileContent(filepath, file.content);
|
|
2500
2461
|
console.log(`Created ${filepath}`);
|
|
@@ -2637,7 +2598,7 @@ async function watchCommand() {
|
|
|
2637
2598
|
|
|
2638
2599
|
// src/cli/index.ts
|
|
2639
2600
|
var program = new import_commander.Command();
|
|
2640
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
2601
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.43.0");
|
|
2641
2602
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
2642
2603
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
2643
2604
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|