rulesync 0.47.0 → 0.49.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/README.ja.md +6 -1
- package/README.md +6 -1
- package/dist/augmentcode-KTXT5GMO.js +9 -0
- package/dist/{chunk-7UVBAWYG.js → chunk-6MFEIYHN.js} +1 -1
- package/dist/chunk-6TAURCQP.js +111 -0
- package/dist/{chunk-P6KQZULZ.js → chunk-G5LLOIO4.js} +1 -1
- package/dist/{chunk-7ZIUEZZQ.js → chunk-IBJGN3JQ.js} +2 -0
- package/dist/{chunk-L2JTXZZB.js → chunk-MCADLVGY.js} +1 -1
- package/dist/{chunk-JWN6GRG6.js → chunk-QNHGYRJT.js} +1 -1
- package/dist/{chunk-D365OP7N.js → chunk-R5HFWJ5L.js} +1 -1
- package/dist/{chunk-BY6RI77W.js → chunk-XHNIEO22.js} +1 -1
- package/dist/{chunk-OTCCHS7Q.js → chunk-YVRWBSCK.js} +1 -1
- package/dist/{claudecode-Y3GIXDUN.js → claudecode-OE4TSKPS.js} +2 -2
- package/dist/{cline-NS3OPXM2.js → cline-CWLQS5CV.js} +2 -2
- package/dist/{copilot-QN2SC7Y2.js → copilot-PVZDRAU5.js} +2 -2
- package/dist/{cursor-DV2IS7JF.js → cursor-ZZV7AY6H.js} +2 -2
- package/dist/{geminicli-MRYTLT2T.js → geminicli-RSXOWFEN.js} +2 -2
- package/dist/index.cjs +922 -551
- package/dist/index.js +889 -575
- package/dist/{kiro-S5TSM7VW.js → kiro-YRKVCDIQ.js} +2 -2
- package/dist/{roo-NWLD3YYN.js → roo-HCRGELWQ.js} +2 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -33,6 +33,8 @@ var init_tool_targets = __esm({
|
|
|
33
33
|
"use strict";
|
|
34
34
|
import_mini = require("zod/mini");
|
|
35
35
|
ToolTargetSchema = import_mini.z.enum([
|
|
36
|
+
"augmentcode",
|
|
37
|
+
"augmentcode-legacy",
|
|
36
38
|
"copilot",
|
|
37
39
|
"cursor",
|
|
38
40
|
"cline",
|
|
@@ -71,6 +73,63 @@ var init_mcp_helpers = __esm({
|
|
|
71
73
|
}
|
|
72
74
|
});
|
|
73
75
|
|
|
76
|
+
// src/generators/mcp/augmentcode.ts
|
|
77
|
+
function generateAugmentcodeMcp(config) {
|
|
78
|
+
const augmentSettings = {
|
|
79
|
+
mcpServers: []
|
|
80
|
+
};
|
|
81
|
+
const shouldInclude = (server) => {
|
|
82
|
+
return shouldIncludeServer(server, "augmentcode");
|
|
83
|
+
};
|
|
84
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
85
|
+
if (!shouldInclude(server)) continue;
|
|
86
|
+
const augmentServer = {
|
|
87
|
+
name: serverName
|
|
88
|
+
};
|
|
89
|
+
if (server.command) {
|
|
90
|
+
augmentServer.command = server.command;
|
|
91
|
+
if (server.args) {
|
|
92
|
+
augmentServer.args = server.args;
|
|
93
|
+
}
|
|
94
|
+
} else if (server.url || server.httpUrl) {
|
|
95
|
+
const url = server.httpUrl || server.url;
|
|
96
|
+
if (url) {
|
|
97
|
+
augmentServer.url = url;
|
|
98
|
+
}
|
|
99
|
+
if (server.httpUrl || server.transport === "http") {
|
|
100
|
+
augmentServer.transport = "http";
|
|
101
|
+
} else if (server.transport === "sse") {
|
|
102
|
+
augmentServer.transport = "sse";
|
|
103
|
+
}
|
|
104
|
+
if (server.env) {
|
|
105
|
+
augmentServer.headers = server.env;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (server.env && server.command) {
|
|
109
|
+
augmentServer.env = server.env;
|
|
110
|
+
}
|
|
111
|
+
if (server.timeout) {
|
|
112
|
+
augmentServer.timeout = server.timeout;
|
|
113
|
+
}
|
|
114
|
+
if (server.disabled !== void 0) {
|
|
115
|
+
augmentServer.enabled = !server.disabled;
|
|
116
|
+
}
|
|
117
|
+
if (server.networkTimeout && server.networkTimeout > 0) {
|
|
118
|
+
augmentServer.retries = Math.max(1, Math.floor(server.networkTimeout / 3e4));
|
|
119
|
+
}
|
|
120
|
+
if (augmentSettings.mcpServers) {
|
|
121
|
+
augmentSettings.mcpServers.push(augmentServer);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return JSON.stringify(augmentSettings, null, 2);
|
|
125
|
+
}
|
|
126
|
+
var init_augmentcode = __esm({
|
|
127
|
+
"src/generators/mcp/augmentcode.ts"() {
|
|
128
|
+
"use strict";
|
|
129
|
+
init_mcp_helpers();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
74
133
|
// src/generators/mcp/claudecode.ts
|
|
75
134
|
function generateClaudeMcp(config) {
|
|
76
135
|
const claudeSettings = {
|
|
@@ -411,6 +470,8 @@ function getDefaultConfig() {
|
|
|
411
470
|
return {
|
|
412
471
|
aiRulesDir: ".rulesync",
|
|
413
472
|
outputPaths: {
|
|
473
|
+
augmentcode: ".",
|
|
474
|
+
"augmentcode-legacy": ".",
|
|
414
475
|
copilot: ".github/instructions",
|
|
415
476
|
cursor: ".cursor/rules",
|
|
416
477
|
cline: ".clinerules",
|
|
@@ -420,7 +481,16 @@ function getDefaultConfig() {
|
|
|
420
481
|
kiro: ".kiro/steering"
|
|
421
482
|
},
|
|
422
483
|
watchEnabled: false,
|
|
423
|
-
defaultTargets: [
|
|
484
|
+
defaultTargets: [
|
|
485
|
+
"augmentcode",
|
|
486
|
+
"copilot",
|
|
487
|
+
"cursor",
|
|
488
|
+
"cline",
|
|
489
|
+
"claudecode",
|
|
490
|
+
"roo",
|
|
491
|
+
"geminicli",
|
|
492
|
+
"kiro"
|
|
493
|
+
]
|
|
424
494
|
};
|
|
425
495
|
}
|
|
426
496
|
function resolveTargets(targets, config) {
|
|
@@ -467,13 +537,219 @@ async function addCommand(filename) {
|
|
|
467
537
|
}
|
|
468
538
|
}
|
|
469
539
|
|
|
470
|
-
// src/generators/ignore/
|
|
540
|
+
// src/generators/ignore/augmentcode.ts
|
|
471
541
|
var import_node_path = require("path");
|
|
542
|
+
async function generateAugmentCodeIgnoreFiles(rules, config, baseDir) {
|
|
543
|
+
const outputs = [];
|
|
544
|
+
const augmentignoreContent = generateAugmentignoreContent(rules);
|
|
545
|
+
const outputPath = baseDir || process.cwd();
|
|
546
|
+
const filepath = (0, import_node_path.join)(outputPath, ".augmentignore");
|
|
547
|
+
outputs.push({
|
|
548
|
+
tool: "augmentcode",
|
|
549
|
+
filepath,
|
|
550
|
+
content: augmentignoreContent
|
|
551
|
+
});
|
|
552
|
+
return outputs;
|
|
553
|
+
}
|
|
554
|
+
function generateAugmentignoreContent(rules) {
|
|
555
|
+
const lines = [
|
|
556
|
+
"# Generated by rulesync - AugmentCode ignore patterns",
|
|
557
|
+
"# AugmentCode uses a two-tier approach: .gitignore first, then .augmentignore",
|
|
558
|
+
"# This file provides Augment-specific exclusions and re-inclusions",
|
|
559
|
+
""
|
|
560
|
+
];
|
|
561
|
+
lines.push(
|
|
562
|
+
"# Security and Secrets (critical exclusions)",
|
|
563
|
+
"# Environment files",
|
|
564
|
+
".env*",
|
|
565
|
+
"",
|
|
566
|
+
"# Private keys and certificates",
|
|
567
|
+
"*.pem",
|
|
568
|
+
"*.key",
|
|
569
|
+
"*.p12",
|
|
570
|
+
"*.crt",
|
|
571
|
+
"*.der",
|
|
572
|
+
"",
|
|
573
|
+
"# SSH keys",
|
|
574
|
+
"id_rsa*",
|
|
575
|
+
"id_dsa*",
|
|
576
|
+
"",
|
|
577
|
+
"# AWS credentials",
|
|
578
|
+
".aws/",
|
|
579
|
+
"aws-exports.js",
|
|
580
|
+
"",
|
|
581
|
+
"# API keys and tokens",
|
|
582
|
+
"**/apikeys/",
|
|
583
|
+
"**/*_token*",
|
|
584
|
+
"**/*_secret*",
|
|
585
|
+
""
|
|
586
|
+
);
|
|
587
|
+
lines.push(
|
|
588
|
+
"# Build Artifacts and Dependencies",
|
|
589
|
+
"# Build outputs",
|
|
590
|
+
"dist/",
|
|
591
|
+
"build/",
|
|
592
|
+
"out/",
|
|
593
|
+
"target/",
|
|
594
|
+
"",
|
|
595
|
+
"# Dependencies",
|
|
596
|
+
"node_modules/",
|
|
597
|
+
"venv/",
|
|
598
|
+
"*.egg-info/",
|
|
599
|
+
"",
|
|
600
|
+
"# Logs",
|
|
601
|
+
"*.log",
|
|
602
|
+
"logs/",
|
|
603
|
+
"",
|
|
604
|
+
"# Temporary files",
|
|
605
|
+
"*.tmp",
|
|
606
|
+
"*.swp",
|
|
607
|
+
"*.swo",
|
|
608
|
+
"*~",
|
|
609
|
+
""
|
|
610
|
+
);
|
|
611
|
+
lines.push(
|
|
612
|
+
"# Large Files and Media",
|
|
613
|
+
"# Binary files",
|
|
614
|
+
"*.jar",
|
|
615
|
+
"*.png",
|
|
616
|
+
"*.jpg",
|
|
617
|
+
"*.jpeg",
|
|
618
|
+
"*.gif",
|
|
619
|
+
"*.mp4",
|
|
620
|
+
"*.avi",
|
|
621
|
+
"*.zip",
|
|
622
|
+
"*.tar.gz",
|
|
623
|
+
"*.rar",
|
|
624
|
+
"",
|
|
625
|
+
"# Database files",
|
|
626
|
+
"*.sqlite",
|
|
627
|
+
"*.db",
|
|
628
|
+
"*.mdb",
|
|
629
|
+
"",
|
|
630
|
+
"# Data files",
|
|
631
|
+
"*.csv",
|
|
632
|
+
"*.tsv",
|
|
633
|
+
"*.xlsx",
|
|
634
|
+
""
|
|
635
|
+
);
|
|
636
|
+
lines.push(
|
|
637
|
+
"# Performance Optimization",
|
|
638
|
+
"# Exclude files that are too large for effective AI processing",
|
|
639
|
+
"**/*.{mp4,avi,mov,mkv}",
|
|
640
|
+
"**/*.{zip,tar,gz,rar}",
|
|
641
|
+
"**/*.{pdf,doc,docx}",
|
|
642
|
+
"**/logs/**/*.log",
|
|
643
|
+
"",
|
|
644
|
+
"# But include small configuration files",
|
|
645
|
+
"!**/config.{json,yaml,yml}",
|
|
646
|
+
""
|
|
647
|
+
);
|
|
648
|
+
const rulePatterns = extractIgnorePatternsFromRules(rules);
|
|
649
|
+
if (rulePatterns.length > 0) {
|
|
650
|
+
lines.push("# Project-specific patterns from rulesync rules");
|
|
651
|
+
lines.push(...rulePatterns);
|
|
652
|
+
lines.push("");
|
|
653
|
+
}
|
|
654
|
+
lines.push(
|
|
655
|
+
"# Team Collaboration",
|
|
656
|
+
"# Exclude personal IDE settings",
|
|
657
|
+
".vscode/settings.json",
|
|
658
|
+
".idea/workspace.xml",
|
|
659
|
+
"",
|
|
660
|
+
"# But include shared team settings",
|
|
661
|
+
"!.vscode/extensions.json",
|
|
662
|
+
"!.idea/codeStyles/",
|
|
663
|
+
"",
|
|
664
|
+
"# Exclude test fixtures with sensitive data",
|
|
665
|
+
"tests/fixtures/real-data/**",
|
|
666
|
+
"",
|
|
667
|
+
"# Re-include important documentation",
|
|
668
|
+
"!vendor/*/README.md",
|
|
669
|
+
"!third-party/*/LICENSE",
|
|
670
|
+
""
|
|
671
|
+
);
|
|
672
|
+
return lines.join("\n");
|
|
673
|
+
}
|
|
674
|
+
function extractIgnorePatternsFromRules(rules) {
|
|
675
|
+
const patterns = [];
|
|
676
|
+
for (const rule of rules) {
|
|
677
|
+
if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
|
|
678
|
+
for (const glob of rule.frontmatter.globs) {
|
|
679
|
+
if (shouldExcludeFromAugmentCode(glob)) {
|
|
680
|
+
patterns.push(`# Exclude: ${rule.frontmatter.description}`);
|
|
681
|
+
patterns.push(glob);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
const contentPatterns = extractAugmentCodeIgnorePatternsFromContent(rule.content);
|
|
686
|
+
patterns.push(...contentPatterns);
|
|
687
|
+
}
|
|
688
|
+
return patterns;
|
|
689
|
+
}
|
|
690
|
+
function shouldExcludeFromAugmentCode(glob) {
|
|
691
|
+
const excludePatterns = [
|
|
692
|
+
// Large generated files that slow indexing
|
|
693
|
+
"**/assets/generated/**",
|
|
694
|
+
"**/public/build/**",
|
|
695
|
+
// Test fixtures with potentially sensitive data
|
|
696
|
+
"**/tests/fixtures/**",
|
|
697
|
+
"**/test/fixtures/**",
|
|
698
|
+
"**/*.fixture.*",
|
|
699
|
+
// Build outputs that provide little value for AI context
|
|
700
|
+
"**/dist/**",
|
|
701
|
+
"**/build/**",
|
|
702
|
+
"**/coverage/**",
|
|
703
|
+
// Configuration that might contain sensitive data
|
|
704
|
+
"**/config/production/**",
|
|
705
|
+
"**/config/secrets/**",
|
|
706
|
+
"**/deploy/prod/**",
|
|
707
|
+
// Internal documentation
|
|
708
|
+
"**/internal-docs/**",
|
|
709
|
+
"**/proprietary/**",
|
|
710
|
+
"**/personal-notes/**",
|
|
711
|
+
"**/private/**",
|
|
712
|
+
"**/confidential/**"
|
|
713
|
+
];
|
|
714
|
+
return excludePatterns.some((pattern) => {
|
|
715
|
+
const regex = new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*"));
|
|
716
|
+
return regex.test(glob);
|
|
717
|
+
});
|
|
718
|
+
}
|
|
719
|
+
function extractAugmentCodeIgnorePatternsFromContent(content) {
|
|
720
|
+
const patterns = [];
|
|
721
|
+
const lines = content.split("\n");
|
|
722
|
+
for (const line of lines) {
|
|
723
|
+
const trimmed = line.trim();
|
|
724
|
+
if (trimmed.startsWith("# AUGMENT_IGNORE:") || trimmed.startsWith("# augmentignore:")) {
|
|
725
|
+
const pattern = trimmed.replace(/^# (AUGMENT_IGNORE|augmentignore):\s*/, "").trim();
|
|
726
|
+
if (pattern) {
|
|
727
|
+
patterns.push(pattern);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (trimmed.startsWith("# AUGMENT_INCLUDE:") || trimmed.startsWith("# augmentinclude:")) {
|
|
731
|
+
const pattern = trimmed.replace(/^# (AUGMENT_INCLUDE|augmentinclude):\s*/, "").trim();
|
|
732
|
+
if (pattern) {
|
|
733
|
+
patterns.push(`!${pattern}`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
if (trimmed.includes("large file") || trimmed.includes("binary") || trimmed.includes("media")) {
|
|
737
|
+
const matches = trimmed.match(/['"`]([^'"`]+\.(mp4|avi|zip|tar\.gz|rar|pdf|doc|xlsx))['"`]/g);
|
|
738
|
+
if (matches) {
|
|
739
|
+
patterns.push(...matches.map((m) => m.replace(/['"`]/g, "")));
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
return patterns;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// src/generators/ignore/kiro.ts
|
|
747
|
+
var import_node_path2 = require("path");
|
|
472
748
|
async function generateKiroIgnoreFiles(rules, config, baseDir) {
|
|
473
749
|
const outputs = [];
|
|
474
750
|
const aiignoreContent = generateAiignoreContent(rules);
|
|
475
751
|
const outputPath = baseDir || process.cwd();
|
|
476
|
-
const filepath = (0,
|
|
752
|
+
const filepath = (0, import_node_path2.join)(outputPath, ".aiignore");
|
|
477
753
|
outputs.push({
|
|
478
754
|
tool: "kiro",
|
|
479
755
|
filepath,
|
|
@@ -513,7 +789,7 @@ function generateAiignoreContent(rules) {
|
|
|
513
789
|
".env*",
|
|
514
790
|
""
|
|
515
791
|
);
|
|
516
|
-
const rulePatterns =
|
|
792
|
+
const rulePatterns = extractIgnorePatternsFromRules2(rules);
|
|
517
793
|
if (rulePatterns.length > 0) {
|
|
518
794
|
lines.push("# Project-specific exclusions from rulesync rules");
|
|
519
795
|
lines.push(...rulePatterns);
|
|
@@ -521,7 +797,7 @@ function generateAiignoreContent(rules) {
|
|
|
521
797
|
}
|
|
522
798
|
return lines.join("\n");
|
|
523
799
|
}
|
|
524
|
-
function
|
|
800
|
+
function extractIgnorePatternsFromRules2(rules) {
|
|
525
801
|
const patterns = [];
|
|
526
802
|
for (const rule of rules) {
|
|
527
803
|
if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
|
|
@@ -582,23 +858,19 @@ function extractIgnorePatternsFromContent(content) {
|
|
|
582
858
|
return patterns;
|
|
583
859
|
}
|
|
584
860
|
|
|
585
|
-
// src/generators/rules/
|
|
586
|
-
var
|
|
861
|
+
// src/generators/rules/augmentcode.ts
|
|
862
|
+
var import_node_path6 = require("path");
|
|
587
863
|
|
|
588
|
-
// src/
|
|
589
|
-
var
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
}),
|
|
595
|
-
{ deny: [] }
|
|
596
|
-
)
|
|
597
|
-
});
|
|
864
|
+
// src/generators/rules/shared-helpers.ts
|
|
865
|
+
var import_node_path5 = require("path");
|
|
866
|
+
|
|
867
|
+
// src/utils/ignore.ts
|
|
868
|
+
var import_node_path4 = require("path");
|
|
869
|
+
var import_micromatch = __toESM(require("micromatch"), 1);
|
|
598
870
|
|
|
599
871
|
// src/utils/file.ts
|
|
600
872
|
var import_promises2 = require("fs/promises");
|
|
601
|
-
var
|
|
873
|
+
var import_node_path3 = require("path");
|
|
602
874
|
async function ensureDir(dirPath) {
|
|
603
875
|
try {
|
|
604
876
|
await (0, import_promises2.stat)(dirPath);
|
|
@@ -610,7 +882,7 @@ async function readFileContent(filepath) {
|
|
|
610
882
|
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
611
883
|
}
|
|
612
884
|
async function writeFileContent(filepath, content) {
|
|
613
|
-
await ensureDir((0,
|
|
885
|
+
await ensureDir((0, import_node_path3.dirname)(filepath));
|
|
614
886
|
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
615
887
|
}
|
|
616
888
|
async function fileExists(filepath) {
|
|
@@ -624,7 +896,7 @@ async function fileExists(filepath) {
|
|
|
624
896
|
async function findFiles(dir, extension = ".md") {
|
|
625
897
|
try {
|
|
626
898
|
const files = await (0, import_promises2.readdir)(dir);
|
|
627
|
-
return files.filter((file) => file.endsWith(extension)).map((file) => (0,
|
|
899
|
+
return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path3.join)(dir, file));
|
|
628
900
|
} catch {
|
|
629
901
|
return [];
|
|
630
902
|
}
|
|
@@ -664,14 +936,12 @@ async function removeClaudeGeneratedFiles() {
|
|
|
664
936
|
}
|
|
665
937
|
|
|
666
938
|
// src/utils/ignore.ts
|
|
667
|
-
var import_node_path3 = require("path");
|
|
668
|
-
var import_micromatch = __toESM(require("micromatch"), 1);
|
|
669
939
|
var cachedIgnorePatterns = null;
|
|
670
940
|
async function loadIgnorePatterns(baseDir = process.cwd()) {
|
|
671
941
|
if (cachedIgnorePatterns) {
|
|
672
942
|
return cachedIgnorePatterns;
|
|
673
943
|
}
|
|
674
|
-
const ignorePath = (0,
|
|
944
|
+
const ignorePath = (0, import_node_path4.join)(baseDir, ".rulesyncignore");
|
|
675
945
|
if (!await fileExists(ignorePath)) {
|
|
676
946
|
cachedIgnorePatterns = { patterns: [] };
|
|
677
947
|
return cachedIgnorePatterns;
|
|
@@ -714,29 +984,167 @@ function filterIgnoredFiles(files, ignorePatterns) {
|
|
|
714
984
|
return files.filter((file) => !isFileIgnored(file, ignorePatterns));
|
|
715
985
|
}
|
|
716
986
|
|
|
987
|
+
// src/generators/rules/shared-helpers.ts
|
|
988
|
+
function resolveOutputDir(config, tool, baseDir) {
|
|
989
|
+
return baseDir ? (0, import_node_path5.join)(baseDir, config.outputPaths[tool]) : config.outputPaths[tool];
|
|
990
|
+
}
|
|
991
|
+
function createOutputsArray() {
|
|
992
|
+
return [];
|
|
993
|
+
}
|
|
994
|
+
function addOutput(outputs, tool, config, baseDir, relativePath, content) {
|
|
995
|
+
const outputDir = resolveOutputDir(config, tool, baseDir);
|
|
996
|
+
outputs.push({
|
|
997
|
+
tool,
|
|
998
|
+
filepath: (0, import_node_path5.join)(outputDir, relativePath),
|
|
999
|
+
content
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
1003
|
+
const outputs = [];
|
|
1004
|
+
for (const rule of rules) {
|
|
1005
|
+
const content = generatorConfig.generateContent(rule);
|
|
1006
|
+
const outputDir = resolveOutputDir(config, generatorConfig.tool, baseDir);
|
|
1007
|
+
const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : (0, import_node_path5.join)(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
|
|
1008
|
+
outputs.push({
|
|
1009
|
+
tool: generatorConfig.tool,
|
|
1010
|
+
filepath,
|
|
1011
|
+
content
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1015
|
+
if (ignorePatterns.patterns.length > 0) {
|
|
1016
|
+
const ignorePath = baseDir ? (0, import_node_path5.join)(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
|
|
1017
|
+
const ignoreContent = generateIgnoreFile(ignorePatterns.patterns, generatorConfig.tool);
|
|
1018
|
+
outputs.push({
|
|
1019
|
+
tool: generatorConfig.tool,
|
|
1020
|
+
filepath: ignorePath,
|
|
1021
|
+
content: ignoreContent
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
1024
|
+
return outputs;
|
|
1025
|
+
}
|
|
1026
|
+
function generateIgnoreFile(patterns, tool) {
|
|
1027
|
+
const lines = [
|
|
1028
|
+
"# Generated by rulesync from .rulesyncignore",
|
|
1029
|
+
"# This file is automatically generated. Do not edit manually."
|
|
1030
|
+
];
|
|
1031
|
+
if (tool === "copilot") {
|
|
1032
|
+
lines.push("# Note: .copilotignore is not officially supported by GitHub Copilot.");
|
|
1033
|
+
lines.push("# This file is for use with community tools like copilotignore-vscode extension.");
|
|
1034
|
+
}
|
|
1035
|
+
lines.push("");
|
|
1036
|
+
lines.push(...patterns);
|
|
1037
|
+
return lines.join("\n");
|
|
1038
|
+
}
|
|
1039
|
+
async function generateComplexRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
1040
|
+
const unifiedConfig = {
|
|
1041
|
+
tool: generatorConfig.tool,
|
|
1042
|
+
fileExtension: generatorConfig.fileExtension,
|
|
1043
|
+
ignoreFileName: generatorConfig.ignoreFileName,
|
|
1044
|
+
generateContent: generatorConfig.generateContent,
|
|
1045
|
+
pathResolver: generatorConfig.getOutputPath
|
|
1046
|
+
};
|
|
1047
|
+
return generateRulesConfig(rules, config, unifiedConfig, baseDir);
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// src/generators/rules/augmentcode.ts
|
|
1051
|
+
async function generateAugmentcodeConfig(rules, config, baseDir) {
|
|
1052
|
+
const outputs = createOutputsArray();
|
|
1053
|
+
rules.forEach((rule) => {
|
|
1054
|
+
addOutput(
|
|
1055
|
+
outputs,
|
|
1056
|
+
"augmentcode",
|
|
1057
|
+
config,
|
|
1058
|
+
baseDir,
|
|
1059
|
+
(0, import_node_path6.join)(".augment", "rules", `${rule.filename}.md`),
|
|
1060
|
+
generateRuleFile(rule)
|
|
1061
|
+
);
|
|
1062
|
+
});
|
|
1063
|
+
return outputs;
|
|
1064
|
+
}
|
|
1065
|
+
function generateRuleFile(rule) {
|
|
1066
|
+
const lines = [];
|
|
1067
|
+
lines.push("---");
|
|
1068
|
+
let ruleType = "manual";
|
|
1069
|
+
let description = rule.frontmatter.description;
|
|
1070
|
+
if (rule.filename.endsWith("-always")) {
|
|
1071
|
+
ruleType = "always";
|
|
1072
|
+
description = "";
|
|
1073
|
+
} else if (rule.filename.endsWith("-auto")) {
|
|
1074
|
+
ruleType = "auto";
|
|
1075
|
+
}
|
|
1076
|
+
lines.push(`type: ${ruleType}`);
|
|
1077
|
+
lines.push(`description: "${description}"`);
|
|
1078
|
+
if (rule.frontmatter.tags && Array.isArray(rule.frontmatter.tags) && rule.frontmatter.tags.length > 0) {
|
|
1079
|
+
lines.push(`tags: [${rule.frontmatter.tags.map((tag) => `"${tag}"`).join(", ")}]`);
|
|
1080
|
+
}
|
|
1081
|
+
lines.push("---");
|
|
1082
|
+
lines.push("");
|
|
1083
|
+
lines.push(rule.content.trim());
|
|
1084
|
+
return lines.join("\n");
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// src/generators/rules/augmentcode-legacy.ts
|
|
1088
|
+
async function generateAugmentcodeLegacyConfig(rules, config, baseDir) {
|
|
1089
|
+
const outputs = createOutputsArray();
|
|
1090
|
+
if (rules.length > 0) {
|
|
1091
|
+
addOutput(
|
|
1092
|
+
outputs,
|
|
1093
|
+
"augmentcode-legacy",
|
|
1094
|
+
config,
|
|
1095
|
+
baseDir,
|
|
1096
|
+
".augment-guidelines",
|
|
1097
|
+
generateLegacyGuidelinesFile(rules)
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
return outputs;
|
|
1101
|
+
}
|
|
1102
|
+
function generateLegacyGuidelinesFile(allRules) {
|
|
1103
|
+
const lines = [];
|
|
1104
|
+
for (const rule of allRules) {
|
|
1105
|
+
lines.push(rule.content.trim());
|
|
1106
|
+
lines.push("");
|
|
1107
|
+
}
|
|
1108
|
+
return lines.join("\n").trim();
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// src/generators/rules/claudecode.ts
|
|
1112
|
+
var import_node_path7 = require("path");
|
|
1113
|
+
|
|
1114
|
+
// src/types/claudecode.ts
|
|
1115
|
+
var import_mini2 = require("zod/mini");
|
|
1116
|
+
var ClaudeSettingsSchema = import_mini2.z.looseObject({
|
|
1117
|
+
permissions: import_mini2.z._default(
|
|
1118
|
+
import_mini2.z.looseObject({
|
|
1119
|
+
deny: import_mini2.z._default(import_mini2.z.array(import_mini2.z.string()), [])
|
|
1120
|
+
}),
|
|
1121
|
+
{ deny: [] }
|
|
1122
|
+
)
|
|
1123
|
+
});
|
|
1124
|
+
|
|
717
1125
|
// src/generators/rules/claudecode.ts
|
|
718
1126
|
async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
719
1127
|
const outputs = [];
|
|
720
1128
|
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
721
1129
|
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
722
1130
|
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
723
|
-
const claudeOutputDir = baseDir ? (0,
|
|
1131
|
+
const claudeOutputDir = baseDir ? (0, import_node_path7.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
|
|
724
1132
|
outputs.push({
|
|
725
1133
|
tool: "claudecode",
|
|
726
|
-
filepath: (0,
|
|
1134
|
+
filepath: (0, import_node_path7.join)(claudeOutputDir, "CLAUDE.md"),
|
|
727
1135
|
content: claudeMdContent
|
|
728
1136
|
});
|
|
729
1137
|
for (const rule of detailRules) {
|
|
730
1138
|
const memoryContent = generateMemoryFile(rule);
|
|
731
1139
|
outputs.push({
|
|
732
1140
|
tool: "claudecode",
|
|
733
|
-
filepath: (0,
|
|
1141
|
+
filepath: (0, import_node_path7.join)(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
|
|
734
1142
|
content: memoryContent
|
|
735
1143
|
});
|
|
736
1144
|
}
|
|
737
1145
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
738
1146
|
if (ignorePatterns.patterns.length > 0) {
|
|
739
|
-
const settingsPath = baseDir ? (0,
|
|
1147
|
+
const settingsPath = baseDir ? (0, import_node_path7.join)(baseDir, ".claude", "settings.json") : (0, import_node_path7.join)(".claude", "settings.json");
|
|
740
1148
|
await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
|
|
741
1149
|
}
|
|
742
1150
|
return outputs;
|
|
@@ -800,70 +1208,38 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
|
|
|
800
1208
|
}
|
|
801
1209
|
|
|
802
1210
|
// src/generators/rules/cline.ts
|
|
803
|
-
var import_node_path5 = require("path");
|
|
804
1211
|
async function generateClineConfig(rules, config, baseDir) {
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
const filepath = (0, import_node_path5.join)(outputDir, `${rule.filename}.md`);
|
|
810
|
-
outputs.push({
|
|
811
|
-
tool: "cline",
|
|
812
|
-
filepath,
|
|
813
|
-
content
|
|
814
|
-
});
|
|
815
|
-
}
|
|
816
|
-
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
817
|
-
if (ignorePatterns.patterns.length > 0) {
|
|
818
|
-
const clineIgnorePath = baseDir ? (0, import_node_path5.join)(baseDir, ".clineignore") : ".clineignore";
|
|
819
|
-
const clineIgnoreContent = generateClineIgnore(ignorePatterns.patterns);
|
|
820
|
-
outputs.push({
|
|
1212
|
+
return generateRulesConfig(
|
|
1213
|
+
rules,
|
|
1214
|
+
config,
|
|
1215
|
+
{
|
|
821
1216
|
tool: "cline",
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
function generateClineMarkdown(rule) {
|
|
829
|
-
return rule.content.trim();
|
|
830
|
-
}
|
|
831
|
-
function generateClineIgnore(patterns) {
|
|
832
|
-
const lines = [
|
|
833
|
-
"# Generated by rulesync from .rulesyncignore",
|
|
834
|
-
"# This file is automatically generated. Do not edit manually.",
|
|
835
|
-
"",
|
|
836
|
-
...patterns
|
|
837
|
-
];
|
|
838
|
-
return lines.join("\n");
|
|
1217
|
+
fileExtension: ".md",
|
|
1218
|
+
ignoreFileName: ".clineignore",
|
|
1219
|
+
generateContent: (rule) => rule.content.trim()
|
|
1220
|
+
},
|
|
1221
|
+
baseDir
|
|
1222
|
+
);
|
|
839
1223
|
}
|
|
840
1224
|
|
|
841
1225
|
// src/generators/rules/copilot.ts
|
|
842
|
-
var
|
|
1226
|
+
var import_node_path8 = require("path");
|
|
843
1227
|
async function generateCopilotConfig(rules, config, baseDir) {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
const outputDir = baseDir ? (0, import_node_path6.join)(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
|
|
849
|
-
const filepath = (0, import_node_path6.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
850
|
-
outputs.push({
|
|
851
|
-
tool: "copilot",
|
|
852
|
-
filepath,
|
|
853
|
-
content
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
857
|
-
if (ignorePatterns.patterns.length > 0) {
|
|
858
|
-
const copilotIgnorePath = baseDir ? (0, import_node_path6.join)(baseDir, ".copilotignore") : ".copilotignore";
|
|
859
|
-
const copilotIgnoreContent = generateCopilotIgnore(ignorePatterns.patterns);
|
|
860
|
-
outputs.push({
|
|
1228
|
+
return generateComplexRulesConfig(
|
|
1229
|
+
rules,
|
|
1230
|
+
config,
|
|
1231
|
+
{
|
|
861
1232
|
tool: "copilot",
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1233
|
+
fileExtension: ".instructions.md",
|
|
1234
|
+
ignoreFileName: ".copilotignore",
|
|
1235
|
+
generateContent: generateCopilotMarkdown,
|
|
1236
|
+
getOutputPath: (rule, outputDir) => {
|
|
1237
|
+
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
1238
|
+
return (0, import_node_path8.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
1239
|
+
}
|
|
1240
|
+
},
|
|
1241
|
+
baseDir
|
|
1242
|
+
);
|
|
867
1243
|
}
|
|
868
1244
|
function generateCopilotMarkdown(rule) {
|
|
869
1245
|
const lines = [];
|
|
@@ -878,43 +1254,24 @@ function generateCopilotMarkdown(rule) {
|
|
|
878
1254
|
lines.push(rule.content);
|
|
879
1255
|
return lines.join("\n");
|
|
880
1256
|
}
|
|
881
|
-
function generateCopilotIgnore(patterns) {
|
|
882
|
-
const lines = [
|
|
883
|
-
"# Generated by rulesync from .rulesyncignore",
|
|
884
|
-
"# This file is automatically generated. Do not edit manually.",
|
|
885
|
-
"# Note: .copilotignore is not officially supported by GitHub Copilot.",
|
|
886
|
-
"# This file is for use with community tools like copilotignore-vscode extension.",
|
|
887
|
-
"",
|
|
888
|
-
...patterns
|
|
889
|
-
];
|
|
890
|
-
return lines.join("\n");
|
|
891
|
-
}
|
|
892
1257
|
|
|
893
1258
|
// src/generators/rules/cursor.ts
|
|
894
|
-
var
|
|
1259
|
+
var import_node_path9 = require("path");
|
|
895
1260
|
async function generateCursorConfig(rules, config, baseDir) {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
const filepath = (0, import_node_path7.join)(outputDir, `${rule.filename}.mdc`);
|
|
901
|
-
outputs.push({
|
|
902
|
-
tool: "cursor",
|
|
903
|
-
filepath,
|
|
904
|
-
content
|
|
905
|
-
});
|
|
906
|
-
}
|
|
907
|
-
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
908
|
-
if (ignorePatterns.patterns.length > 0) {
|
|
909
|
-
const cursorIgnorePath = baseDir ? (0, import_node_path7.join)(baseDir, ".cursorignore") : ".cursorignore";
|
|
910
|
-
const cursorIgnoreContent = generateCursorIgnore(ignorePatterns.patterns);
|
|
911
|
-
outputs.push({
|
|
1261
|
+
return generateComplexRulesConfig(
|
|
1262
|
+
rules,
|
|
1263
|
+
config,
|
|
1264
|
+
{
|
|
912
1265
|
tool: "cursor",
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1266
|
+
fileExtension: ".mdc",
|
|
1267
|
+
ignoreFileName: ".cursorignore",
|
|
1268
|
+
generateContent: generateCursorMarkdown,
|
|
1269
|
+
getOutputPath: (rule, outputDir) => {
|
|
1270
|
+
return (0, import_node_path9.join)(outputDir, `${rule.filename}.mdc`);
|
|
1271
|
+
}
|
|
1272
|
+
},
|
|
1273
|
+
baseDir
|
|
1274
|
+
);
|
|
918
1275
|
}
|
|
919
1276
|
function generateCursorMarkdown(rule) {
|
|
920
1277
|
const lines = [];
|
|
@@ -968,26 +1325,17 @@ function determineCursorRuleType(frontmatter) {
|
|
|
968
1325
|
}
|
|
969
1326
|
return "intelligently";
|
|
970
1327
|
}
|
|
971
|
-
function generateCursorIgnore(patterns) {
|
|
972
|
-
const lines = [
|
|
973
|
-
"# Generated by rulesync from .rulesyncignore",
|
|
974
|
-
"# This file is automatically generated. Do not edit manually.",
|
|
975
|
-
"",
|
|
976
|
-
...patterns
|
|
977
|
-
];
|
|
978
|
-
return lines.join("\n");
|
|
979
|
-
}
|
|
980
1328
|
|
|
981
1329
|
// src/generators/rules/geminicli.ts
|
|
982
|
-
var
|
|
1330
|
+
var import_node_path10 = require("path");
|
|
983
1331
|
async function generateGeminiConfig(rules, config, baseDir) {
|
|
984
1332
|
const outputs = [];
|
|
985
1333
|
const rootRule = rules.find((rule) => rule.frontmatter.root === true);
|
|
986
1334
|
const memoryRules = rules.filter((rule) => rule.frontmatter.root === false);
|
|
987
1335
|
for (const rule of memoryRules) {
|
|
988
1336
|
const content = generateGeminiMemoryMarkdown(rule);
|
|
989
|
-
const outputDir = baseDir ? (0,
|
|
990
|
-
const filepath = (0,
|
|
1337
|
+
const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
|
|
1338
|
+
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
991
1339
|
outputs.push({
|
|
992
1340
|
tool: "geminicli",
|
|
993
1341
|
filepath,
|
|
@@ -995,7 +1343,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
|
|
|
995
1343
|
});
|
|
996
1344
|
}
|
|
997
1345
|
const rootContent = generateGeminiRootMarkdown(rootRule, memoryRules, baseDir);
|
|
998
|
-
const rootFilepath = baseDir ? (0,
|
|
1346
|
+
const rootFilepath = baseDir ? (0, import_node_path10.join)(baseDir, "GEMINI.md") : "GEMINI.md";
|
|
999
1347
|
outputs.push({
|
|
1000
1348
|
tool: "geminicli",
|
|
1001
1349
|
filepath: rootFilepath,
|
|
@@ -1003,7 +1351,7 @@ async function generateGeminiConfig(rules, config, baseDir) {
|
|
|
1003
1351
|
});
|
|
1004
1352
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1005
1353
|
if (ignorePatterns.patterns.length > 0) {
|
|
1006
|
-
const aiexcludePath = baseDir ? (0,
|
|
1354
|
+
const aiexcludePath = baseDir ? (0, import_node_path10.join)(baseDir, ".aiexclude") : ".aiexclude";
|
|
1007
1355
|
const aiexcludeContent = generateAiexclude(ignorePatterns.patterns);
|
|
1008
1356
|
outputs.push({
|
|
1009
1357
|
tool: "geminicli",
|
|
@@ -1051,13 +1399,13 @@ function generateAiexclude(patterns) {
|
|
|
1051
1399
|
}
|
|
1052
1400
|
|
|
1053
1401
|
// src/generators/rules/kiro.ts
|
|
1054
|
-
var
|
|
1402
|
+
var import_node_path11 = require("path");
|
|
1055
1403
|
async function generateKiroConfig(rules, config, baseDir) {
|
|
1056
1404
|
const outputs = [];
|
|
1057
1405
|
for (const rule of rules) {
|
|
1058
1406
|
const content = generateKiroMarkdown(rule);
|
|
1059
|
-
const outputDir = baseDir ? (0,
|
|
1060
|
-
const filepath = (0,
|
|
1407
|
+
const outputDir = baseDir ? (0, import_node_path11.join)(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
|
|
1408
|
+
const filepath = (0, import_node_path11.join)(outputDir, `${rule.filename}.md`);
|
|
1061
1409
|
outputs.push({
|
|
1062
1410
|
tool: "kiro",
|
|
1063
1411
|
filepath,
|
|
@@ -1071,47 +1419,23 @@ function generateKiroMarkdown(rule) {
|
|
|
1071
1419
|
}
|
|
1072
1420
|
|
|
1073
1421
|
// src/generators/rules/roo.ts
|
|
1074
|
-
var import_node_path10 = require("path");
|
|
1075
1422
|
async function generateRooConfig(rules, config, baseDir) {
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
1081
|
-
outputs.push({
|
|
1082
|
-
tool: "roo",
|
|
1083
|
-
filepath,
|
|
1084
|
-
content
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1088
|
-
if (ignorePatterns.patterns.length > 0) {
|
|
1089
|
-
const rooIgnorePath = baseDir ? (0, import_node_path10.join)(baseDir, ".rooignore") : ".rooignore";
|
|
1090
|
-
const rooIgnoreContent = generateRooIgnore(ignorePatterns.patterns);
|
|
1091
|
-
outputs.push({
|
|
1423
|
+
return generateRulesConfig(
|
|
1424
|
+
rules,
|
|
1425
|
+
config,
|
|
1426
|
+
{
|
|
1092
1427
|
tool: "roo",
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
function generateRooMarkdown(rule) {
|
|
1100
|
-
return rule.content.trim();
|
|
1101
|
-
}
|
|
1102
|
-
function generateRooIgnore(patterns) {
|
|
1103
|
-
const lines = [
|
|
1104
|
-
"# Generated by rulesync from .rulesyncignore",
|
|
1105
|
-
"# This file is automatically generated. Do not edit manually.",
|
|
1106
|
-
"",
|
|
1107
|
-
...patterns
|
|
1108
|
-
];
|
|
1109
|
-
return lines.join("\n");
|
|
1428
|
+
fileExtension: ".md",
|
|
1429
|
+
ignoreFileName: ".rooignore",
|
|
1430
|
+
generateContent: (rule) => rule.content.trim()
|
|
1431
|
+
},
|
|
1432
|
+
baseDir
|
|
1433
|
+
);
|
|
1110
1434
|
}
|
|
1111
1435
|
|
|
1112
1436
|
// src/core/generator.ts
|
|
1113
1437
|
async function generateConfigurations(rules, config, targetTools, baseDir) {
|
|
1114
|
-
const outputs =
|
|
1438
|
+
const outputs = createOutputsArray();
|
|
1115
1439
|
const toolsToGenerate = targetTools || config.defaultTargets;
|
|
1116
1440
|
const rootFiles = rules.filter((rule) => rule.frontmatter.root === true);
|
|
1117
1441
|
if (rootFiles.length === 0) {
|
|
@@ -1140,6 +1464,20 @@ function filterRulesForTool(rules, tool, config) {
|
|
|
1140
1464
|
}
|
|
1141
1465
|
async function generateForTool(tool, rules, config, baseDir) {
|
|
1142
1466
|
switch (tool) {
|
|
1467
|
+
case "augmentcode": {
|
|
1468
|
+
const augmentRulesOutputs = await generateAugmentcodeConfig(rules, config, baseDir);
|
|
1469
|
+
const augmentIgnoreOutputs = await generateAugmentCodeIgnoreFiles(rules, config, baseDir);
|
|
1470
|
+
return [...augmentRulesOutputs, ...augmentIgnoreOutputs];
|
|
1471
|
+
}
|
|
1472
|
+
case "augmentcode-legacy": {
|
|
1473
|
+
const augmentLegacyRulesOutputs = await generateAugmentcodeLegacyConfig(
|
|
1474
|
+
rules,
|
|
1475
|
+
config,
|
|
1476
|
+
baseDir
|
|
1477
|
+
);
|
|
1478
|
+
const augmentIgnoreOutputs = await generateAugmentCodeIgnoreFiles(rules, config, baseDir);
|
|
1479
|
+
return [...augmentLegacyRulesOutputs, ...augmentIgnoreOutputs];
|
|
1480
|
+
}
|
|
1143
1481
|
case "copilot":
|
|
1144
1482
|
return generateCopilotConfig(rules, config, baseDir);
|
|
1145
1483
|
case "cursor":
|
|
@@ -1164,7 +1502,7 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
1164
1502
|
}
|
|
1165
1503
|
|
|
1166
1504
|
// src/core/parser.ts
|
|
1167
|
-
var
|
|
1505
|
+
var import_node_path12 = require("path");
|
|
1168
1506
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
1169
1507
|
|
|
1170
1508
|
// src/types/config.ts
|
|
@@ -1217,7 +1555,8 @@ var RuleFrontmatterSchema = import_mini5.z.object({
|
|
|
1217
1555
|
targets: RulesyncTargetsSchema,
|
|
1218
1556
|
description: import_mini5.z.string(),
|
|
1219
1557
|
globs: import_mini5.z.array(import_mini5.z.string()),
|
|
1220
|
-
cursorRuleType: import_mini5.z.optional(import_mini5.z.enum(["always", "manual", "specificFiles", "intelligently"]))
|
|
1558
|
+
cursorRuleType: import_mini5.z.optional(import_mini5.z.enum(["always", "manual", "specificFiles", "intelligently"])),
|
|
1559
|
+
tags: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string()))
|
|
1221
1560
|
});
|
|
1222
1561
|
var ParsedRuleSchema = import_mini5.z.object({
|
|
1223
1562
|
frontmatter: RuleFrontmatterSchema,
|
|
@@ -1276,7 +1615,7 @@ async function parseRuleFile(filepath) {
|
|
|
1276
1615
|
const parsed = (0, import_gray_matter.default)(content);
|
|
1277
1616
|
try {
|
|
1278
1617
|
const frontmatter = RuleFrontmatterSchema.parse(parsed.data);
|
|
1279
|
-
const filename = (0,
|
|
1618
|
+
const filename = (0, import_node_path12.basename)(filepath, ".md");
|
|
1280
1619
|
return {
|
|
1281
1620
|
frontmatter,
|
|
1282
1621
|
content: parsed.content,
|
|
@@ -1344,6 +1683,7 @@ async function validateRule(rule) {
|
|
|
1344
1683
|
var path3 = __toESM(require("path"), 1);
|
|
1345
1684
|
|
|
1346
1685
|
// src/generators/mcp/index.ts
|
|
1686
|
+
init_augmentcode();
|
|
1347
1687
|
init_claudecode();
|
|
1348
1688
|
init_cline();
|
|
1349
1689
|
init_copilot();
|
|
@@ -1388,6 +1728,16 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
1388
1728
|
return results;
|
|
1389
1729
|
}
|
|
1390
1730
|
const generators = [
|
|
1731
|
+
{
|
|
1732
|
+
tool: "augmentcode-project",
|
|
1733
|
+
path: path3.join(targetRoot, ".mcp.json"),
|
|
1734
|
+
generate: () => generateAugmentcodeMcp(config)
|
|
1735
|
+
},
|
|
1736
|
+
{
|
|
1737
|
+
tool: "augmentcode-legacy-project",
|
|
1738
|
+
path: path3.join(targetRoot, ".mcp.json"),
|
|
1739
|
+
generate: () => generateAugmentcodeMcp(config)
|
|
1740
|
+
},
|
|
1391
1741
|
{
|
|
1392
1742
|
tool: "claude-project",
|
|
1393
1743
|
path: path3.join(targetRoot, ".mcp.json"),
|
|
@@ -1428,7 +1778,7 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
1428
1778
|
try {
|
|
1429
1779
|
const content = generator.generate();
|
|
1430
1780
|
const parsed = JSON.parse(content);
|
|
1431
|
-
if (generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
1781
|
+
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
1432
1782
|
if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
|
|
1433
1783
|
results.push({
|
|
1434
1784
|
tool: generator.tool,
|
|
@@ -1547,11 +1897,10 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1547
1897
|
console.warn("\u26A0\uFE0F No configurations generated");
|
|
1548
1898
|
return;
|
|
1549
1899
|
}
|
|
1550
|
-
console.log(`
|
|
1551
|
-
\u{1F389} Successfully generated ${totalOutputs} configuration file(s)!`);
|
|
1552
1900
|
if (options.verbose) {
|
|
1553
1901
|
console.log("\nGenerating MCP configurations...");
|
|
1554
1902
|
}
|
|
1903
|
+
let totalMcpOutputs = 0;
|
|
1555
1904
|
for (const baseDir of baseDirs) {
|
|
1556
1905
|
const mcpResults = await generateMcpConfigs(
|
|
1557
1906
|
process.cwd(),
|
|
@@ -1566,6 +1915,7 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1566
1915
|
for (const result of mcpResults) {
|
|
1567
1916
|
if (result.status === "success") {
|
|
1568
1917
|
console.log(`\u2705 Generated ${result.tool} MCP configuration: ${result.path}`);
|
|
1918
|
+
totalMcpOutputs++;
|
|
1569
1919
|
} else if (result.status === "error") {
|
|
1570
1920
|
console.error(`\u274C Failed to generate ${result.tool} MCP configuration: ${result.error}`);
|
|
1571
1921
|
} else if (options.verbose && result.status === "skipped") {
|
|
@@ -1573,6 +1923,13 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1573
1923
|
}
|
|
1574
1924
|
}
|
|
1575
1925
|
}
|
|
1926
|
+
const totalGenerated = totalOutputs + totalMcpOutputs;
|
|
1927
|
+
if (totalGenerated > 0) {
|
|
1928
|
+
console.log(
|
|
1929
|
+
`
|
|
1930
|
+
\u{1F389} All done! Generated ${totalGenerated} file(s) total (${totalOutputs} configurations + ${totalMcpOutputs} MCP configurations)`
|
|
1931
|
+
);
|
|
1932
|
+
}
|
|
1576
1933
|
} catch (error) {
|
|
1577
1934
|
console.error("\u274C Failed to generate configurations:", error);
|
|
1578
1935
|
process.exit(1);
|
|
@@ -1581,9 +1938,9 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1581
1938
|
|
|
1582
1939
|
// src/cli/commands/gitignore.ts
|
|
1583
1940
|
var import_node_fs = require("fs");
|
|
1584
|
-
var
|
|
1941
|
+
var import_node_path13 = require("path");
|
|
1585
1942
|
var gitignoreCommand = async () => {
|
|
1586
|
-
const gitignorePath = (0,
|
|
1943
|
+
const gitignorePath = (0, import_node_path13.join)(process.cwd(), ".gitignore");
|
|
1587
1944
|
const rulesFilesToIgnore = [
|
|
1588
1945
|
"# Generated by rulesync - AI tool configuration files",
|
|
1589
1946
|
"**/.github/copilot-instructions.md",
|
|
@@ -1601,7 +1958,10 @@ var gitignoreCommand = async () => {
|
|
|
1601
1958
|
"**/.gemini/memories/",
|
|
1602
1959
|
"**/.aiexclude",
|
|
1603
1960
|
"**/.aiignore",
|
|
1961
|
+
"**/.augmentignore",
|
|
1604
1962
|
"**/.kiro/steering/",
|
|
1963
|
+
"**/.augment/rules/",
|
|
1964
|
+
"**/.augment-guidelines",
|
|
1605
1965
|
"**/.mcp.json",
|
|
1606
1966
|
"!.rulesync/.mcp.json",
|
|
1607
1967
|
"**/.cursor/mcp.json",
|
|
@@ -1639,35 +1999,273 @@ ${linesToAdd.join("\n")}
|
|
|
1639
1999
|
};
|
|
1640
2000
|
|
|
1641
2001
|
// src/core/importer.ts
|
|
1642
|
-
var
|
|
1643
|
-
var
|
|
2002
|
+
var import_node_path18 = require("path");
|
|
2003
|
+
var import_gray_matter5 = __toESM(require("gray-matter"), 1);
|
|
1644
2004
|
|
|
1645
|
-
// src/parsers/
|
|
1646
|
-
var
|
|
1647
|
-
|
|
2005
|
+
// src/parsers/augmentcode.ts
|
|
2006
|
+
var import_node_path14 = require("path");
|
|
2007
|
+
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
2008
|
+
|
|
2009
|
+
// src/utils/parser-helpers.ts
|
|
2010
|
+
function createParseResult() {
|
|
2011
|
+
return { rules: [], errors: [] };
|
|
2012
|
+
}
|
|
2013
|
+
function addError(result, error) {
|
|
2014
|
+
result.errors.push(error);
|
|
2015
|
+
}
|
|
2016
|
+
function addRule(result, rule) {
|
|
2017
|
+
if (!result.rules) {
|
|
2018
|
+
result.rules = [];
|
|
2019
|
+
}
|
|
2020
|
+
result.rules.push(rule);
|
|
2021
|
+
}
|
|
2022
|
+
function addRules(result, rules) {
|
|
2023
|
+
if (!result.rules) {
|
|
2024
|
+
result.rules = [];
|
|
2025
|
+
}
|
|
2026
|
+
result.rules.push(...rules);
|
|
2027
|
+
}
|
|
2028
|
+
function handleParseError(error, context) {
|
|
2029
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2030
|
+
return `${context}: ${errorMessage}`;
|
|
2031
|
+
}
|
|
2032
|
+
async function safeReadFile(operation, errorContext) {
|
|
2033
|
+
try {
|
|
2034
|
+
const result = await operation();
|
|
2035
|
+
return { success: true, result };
|
|
2036
|
+
} catch (error) {
|
|
2037
|
+
return {
|
|
2038
|
+
success: false,
|
|
2039
|
+
error: handleParseError(error, errorContext)
|
|
2040
|
+
};
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
// src/parsers/augmentcode.ts
|
|
2045
|
+
async function parseAugmentcodeConfiguration(baseDir = process.cwd()) {
|
|
2046
|
+
const result = createParseResult();
|
|
2047
|
+
const rulesDir = (0, import_node_path14.join)(baseDir, ".augment", "rules");
|
|
2048
|
+
if (await fileExists(rulesDir)) {
|
|
2049
|
+
const rulesResult = await parseAugmentRules(rulesDir);
|
|
2050
|
+
addRules(result, rulesResult.rules);
|
|
2051
|
+
result.errors.push(...rulesResult.errors);
|
|
2052
|
+
} else {
|
|
2053
|
+
addError(result, "No AugmentCode configuration found. Expected .augment/rules/ directory.");
|
|
2054
|
+
}
|
|
2055
|
+
return { rules: result.rules || [], errors: result.errors };
|
|
2056
|
+
}
|
|
2057
|
+
async function parseAugmentRules(rulesDir) {
|
|
2058
|
+
const rules = [];
|
|
2059
|
+
const errors = [];
|
|
2060
|
+
try {
|
|
2061
|
+
const { readdir: readdir2 } = await import("fs/promises");
|
|
2062
|
+
const files = await readdir2(rulesDir);
|
|
2063
|
+
for (const file of files) {
|
|
2064
|
+
if (file.endsWith(".md") || file.endsWith(".mdc")) {
|
|
2065
|
+
const filePath = (0, import_node_path14.join)(rulesDir, file);
|
|
2066
|
+
try {
|
|
2067
|
+
const rawContent = await readFileContent(filePath);
|
|
2068
|
+
const parsed = (0, import_gray_matter2.default)(rawContent);
|
|
2069
|
+
const frontmatterData = parsed.data;
|
|
2070
|
+
const ruleType = frontmatterData.type || "manual";
|
|
2071
|
+
const description = frontmatterData.description || "";
|
|
2072
|
+
const tags = Array.isArray(frontmatterData.tags) ? frontmatterData.tags : void 0;
|
|
2073
|
+
const isRoot = ruleType === "always";
|
|
2074
|
+
const filename = (0, import_node_path14.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
|
|
2075
|
+
const frontmatter = {
|
|
2076
|
+
root: isRoot,
|
|
2077
|
+
targets: ["augmentcode"],
|
|
2078
|
+
description,
|
|
2079
|
+
globs: ["**/*"],
|
|
2080
|
+
// AugmentCode doesn't use specific globs in the same way
|
|
2081
|
+
...tags && { tags }
|
|
2082
|
+
};
|
|
2083
|
+
rules.push({
|
|
2084
|
+
frontmatter,
|
|
2085
|
+
content: parsed.content.trim(),
|
|
2086
|
+
filename: `augmentcode-${ruleType}-${filename}`,
|
|
2087
|
+
filepath: filePath
|
|
2088
|
+
});
|
|
2089
|
+
} catch (error) {
|
|
2090
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2091
|
+
errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
} catch (error) {
|
|
2096
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2097
|
+
errors.push(`Failed to read .augment/rules/ directory: ${errorMessage}`);
|
|
2098
|
+
}
|
|
2099
|
+
return { rules, errors };
|
|
2100
|
+
}
|
|
2101
|
+
|
|
2102
|
+
// src/parsers/augmentcode-legacy.ts
|
|
2103
|
+
var import_node_path15 = require("path");
|
|
2104
|
+
async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
2105
|
+
const result = createParseResult();
|
|
2106
|
+
const guidelinesPath = (0, import_node_path15.join)(baseDir, ".augment-guidelines");
|
|
2107
|
+
if (await fileExists(guidelinesPath)) {
|
|
2108
|
+
const guidelinesResult = await parseAugmentGuidelines(guidelinesPath);
|
|
2109
|
+
if (guidelinesResult.rule) {
|
|
2110
|
+
addRule(result, guidelinesResult.rule);
|
|
2111
|
+
}
|
|
2112
|
+
result.errors.push(...guidelinesResult.errors);
|
|
2113
|
+
} else {
|
|
2114
|
+
addError(
|
|
2115
|
+
result,
|
|
2116
|
+
"No AugmentCode legacy configuration found. Expected .augment-guidelines file."
|
|
2117
|
+
);
|
|
2118
|
+
}
|
|
2119
|
+
return { rules: result.rules || [], errors: result.errors };
|
|
2120
|
+
}
|
|
2121
|
+
async function parseAugmentGuidelines(guidelinesPath) {
|
|
2122
|
+
const parseResult = await safeReadFile(async () => {
|
|
2123
|
+
const content = await readFileContent(guidelinesPath);
|
|
2124
|
+
if (content.trim()) {
|
|
2125
|
+
const frontmatter = {
|
|
2126
|
+
root: true,
|
|
2127
|
+
// Legacy guidelines become root rules
|
|
2128
|
+
targets: ["augmentcode-legacy"],
|
|
2129
|
+
description: "Legacy AugmentCode guidelines",
|
|
2130
|
+
globs: ["**/*"]
|
|
2131
|
+
};
|
|
2132
|
+
return {
|
|
2133
|
+
frontmatter,
|
|
2134
|
+
content: content.trim(),
|
|
2135
|
+
filename: "augmentcode-legacy-guidelines",
|
|
2136
|
+
filepath: guidelinesPath
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
return null;
|
|
2140
|
+
}, "Failed to parse .augment-guidelines");
|
|
2141
|
+
if (parseResult.success) {
|
|
2142
|
+
return { rule: parseResult.result || null, errors: [] };
|
|
2143
|
+
} else {
|
|
2144
|
+
return { rule: null, errors: [parseResult.error || "Unknown error"] };
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
// src/parsers/shared-helpers.ts
|
|
2149
|
+
var import_node_path16 = require("path");
|
|
2150
|
+
var import_gray_matter3 = __toESM(require("gray-matter"), 1);
|
|
2151
|
+
async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
2152
|
+
const errors = [];
|
|
2153
|
+
const rules = [];
|
|
2154
|
+
if (config.mainFile) {
|
|
2155
|
+
const mainFilePath = (0, import_node_path16.join)(baseDir, config.mainFile.path);
|
|
2156
|
+
if (await fileExists(mainFilePath)) {
|
|
2157
|
+
try {
|
|
2158
|
+
const rawContent = await readFileContent(mainFilePath);
|
|
2159
|
+
let content;
|
|
2160
|
+
let frontmatter;
|
|
2161
|
+
if (config.mainFile.useFrontmatter) {
|
|
2162
|
+
const parsed = (0, import_gray_matter3.default)(rawContent);
|
|
2163
|
+
content = parsed.content.trim();
|
|
2164
|
+
frontmatter = {
|
|
2165
|
+
root: false,
|
|
2166
|
+
targets: [config.tool],
|
|
2167
|
+
description: config.mainFile.description,
|
|
2168
|
+
globs: ["**/*"]
|
|
2169
|
+
};
|
|
2170
|
+
} else {
|
|
2171
|
+
content = rawContent.trim();
|
|
2172
|
+
frontmatter = {
|
|
2173
|
+
root: false,
|
|
2174
|
+
targets: [config.tool],
|
|
2175
|
+
description: config.mainFile.description,
|
|
2176
|
+
globs: ["**/*"]
|
|
2177
|
+
};
|
|
2178
|
+
}
|
|
2179
|
+
if (content) {
|
|
2180
|
+
rules.push({
|
|
2181
|
+
frontmatter,
|
|
2182
|
+
content,
|
|
2183
|
+
filename: `${config.tool}-instructions`,
|
|
2184
|
+
filepath: mainFilePath
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
} catch (error) {
|
|
2188
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2189
|
+
errors.push(`Failed to parse ${config.mainFile.path}: ${errorMessage}`);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
if (config.directories) {
|
|
2194
|
+
for (const dirConfig of config.directories) {
|
|
2195
|
+
const dirPath = (0, import_node_path16.join)(baseDir, dirConfig.directory);
|
|
2196
|
+
if (await fileExists(dirPath)) {
|
|
2197
|
+
try {
|
|
2198
|
+
const { readdir: readdir2 } = await import("fs/promises");
|
|
2199
|
+
const files = await readdir2(dirPath);
|
|
2200
|
+
for (const file of files) {
|
|
2201
|
+
if (file.endsWith(dirConfig.filePattern)) {
|
|
2202
|
+
const filePath = (0, import_node_path16.join)(dirPath, file);
|
|
2203
|
+
try {
|
|
2204
|
+
const rawContent = await readFileContent(filePath);
|
|
2205
|
+
let content;
|
|
2206
|
+
if (dirConfig.filePattern === ".instructions.md") {
|
|
2207
|
+
const parsed = (0, import_gray_matter3.default)(rawContent);
|
|
2208
|
+
content = parsed.content.trim();
|
|
2209
|
+
} else {
|
|
2210
|
+
content = rawContent.trim();
|
|
2211
|
+
}
|
|
2212
|
+
if (content) {
|
|
2213
|
+
const filename = file.replace(new RegExp(`\\${dirConfig.filePattern}$`), "");
|
|
2214
|
+
const frontmatter = {
|
|
2215
|
+
root: false,
|
|
2216
|
+
targets: [config.tool],
|
|
2217
|
+
description: `${dirConfig.description}: ${filename}`,
|
|
2218
|
+
globs: ["**/*"]
|
|
2219
|
+
};
|
|
2220
|
+
rules.push({
|
|
2221
|
+
frontmatter,
|
|
2222
|
+
content,
|
|
2223
|
+
filename: `${config.tool}-${filename}`,
|
|
2224
|
+
filepath: filePath
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
} catch (error) {
|
|
2228
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2229
|
+
errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
} catch (error) {
|
|
2234
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2235
|
+
errors.push(`Failed to parse ${dirConfig.directory} files: ${errorMessage}`);
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
if (rules.length === 0) {
|
|
2241
|
+
errors.push(config.errorMessage);
|
|
2242
|
+
}
|
|
2243
|
+
return { rules, errors };
|
|
2244
|
+
}
|
|
2245
|
+
async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
|
|
1648
2246
|
const errors = [];
|
|
1649
2247
|
const rules = [];
|
|
1650
2248
|
let ignorePatterns;
|
|
1651
2249
|
let mcpServers;
|
|
1652
|
-
const
|
|
1653
|
-
if (!await fileExists(
|
|
1654
|
-
errors.push(
|
|
2250
|
+
const mainFilePath = (0, import_node_path16.join)(baseDir, config.mainFileName);
|
|
2251
|
+
if (!await fileExists(mainFilePath)) {
|
|
2252
|
+
errors.push(`${config.mainFileName} file not found`);
|
|
1655
2253
|
return { rules, errors };
|
|
1656
2254
|
}
|
|
1657
2255
|
try {
|
|
1658
|
-
const
|
|
1659
|
-
const mainRule =
|
|
2256
|
+
const mainContent = await readFileContent(mainFilePath);
|
|
2257
|
+
const mainRule = parseMainFile(mainContent, mainFilePath, config);
|
|
1660
2258
|
if (mainRule) {
|
|
1661
2259
|
rules.push(mainRule);
|
|
1662
2260
|
}
|
|
1663
|
-
const memoryDir = (0,
|
|
2261
|
+
const memoryDir = (0, import_node_path16.join)(baseDir, config.memoryDirPath);
|
|
1664
2262
|
if (await fileExists(memoryDir)) {
|
|
1665
|
-
const memoryRules = await
|
|
2263
|
+
const memoryRules = await parseMemoryFiles(memoryDir, config);
|
|
1666
2264
|
rules.push(...memoryRules);
|
|
1667
2265
|
}
|
|
1668
|
-
const settingsPath = (0,
|
|
2266
|
+
const settingsPath = (0, import_node_path16.join)(baseDir, config.settingsPath);
|
|
1669
2267
|
if (await fileExists(settingsPath)) {
|
|
1670
|
-
const settingsResult = await
|
|
2268
|
+
const settingsResult = await parseSettingsFile(settingsPath, config.tool);
|
|
1671
2269
|
if (settingsResult.ignorePatterns) {
|
|
1672
2270
|
ignorePatterns = settingsResult.ignorePatterns;
|
|
1673
2271
|
}
|
|
@@ -1676,9 +2274,18 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
|
1676
2274
|
}
|
|
1677
2275
|
errors.push(...settingsResult.errors);
|
|
1678
2276
|
}
|
|
2277
|
+
if (config.additionalIgnoreFile) {
|
|
2278
|
+
const additionalIgnorePath = (0, import_node_path16.join)(baseDir, config.additionalIgnoreFile.path);
|
|
2279
|
+
if (await fileExists(additionalIgnorePath)) {
|
|
2280
|
+
const additionalPatterns = await config.additionalIgnoreFile.parser(additionalIgnorePath);
|
|
2281
|
+
if (additionalPatterns.length > 0) {
|
|
2282
|
+
ignorePatterns = ignorePatterns ? [...ignorePatterns, ...additionalPatterns] : additionalPatterns;
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
1679
2286
|
} catch (error) {
|
|
1680
2287
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1681
|
-
errors.push(`Failed to parse
|
|
2288
|
+
errors.push(`Failed to parse ${config.tool} configuration: ${errorMessage}`);
|
|
1682
2289
|
}
|
|
1683
2290
|
return {
|
|
1684
2291
|
rules,
|
|
@@ -1687,7 +2294,7 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
|
1687
2294
|
...mcpServers && { mcpServers }
|
|
1688
2295
|
};
|
|
1689
2296
|
}
|
|
1690
|
-
function
|
|
2297
|
+
function parseMainFile(content, filepath, config) {
|
|
1691
2298
|
const lines = content.split("\n");
|
|
1692
2299
|
let contentStartIndex = 0;
|
|
1693
2300
|
if (lines.some((line) => line.includes("| Document | Description | File Patterns |"))) {
|
|
@@ -1704,38 +2311,38 @@ function parseClaudeMainFile(content, filepath) {
|
|
|
1704
2311
|
}
|
|
1705
2312
|
const frontmatter = {
|
|
1706
2313
|
root: false,
|
|
1707
|
-
targets: [
|
|
1708
|
-
description:
|
|
2314
|
+
targets: [config.tool],
|
|
2315
|
+
description: config.mainDescription,
|
|
1709
2316
|
globs: ["**/*"]
|
|
1710
2317
|
};
|
|
1711
2318
|
return {
|
|
1712
2319
|
frontmatter,
|
|
1713
2320
|
content: mainContent,
|
|
1714
|
-
filename:
|
|
2321
|
+
filename: `${config.filenamePrefix}-main`,
|
|
1715
2322
|
filepath
|
|
1716
2323
|
};
|
|
1717
2324
|
}
|
|
1718
|
-
async function
|
|
2325
|
+
async function parseMemoryFiles(memoryDir, config) {
|
|
1719
2326
|
const rules = [];
|
|
1720
2327
|
try {
|
|
1721
2328
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1722
2329
|
const files = await readdir2(memoryDir);
|
|
1723
2330
|
for (const file of files) {
|
|
1724
2331
|
if (file.endsWith(".md")) {
|
|
1725
|
-
const filePath = (0,
|
|
2332
|
+
const filePath = (0, import_node_path16.join)(memoryDir, file);
|
|
1726
2333
|
const content = await readFileContent(filePath);
|
|
1727
2334
|
if (content.trim()) {
|
|
1728
|
-
const filename = (0,
|
|
2335
|
+
const filename = (0, import_node_path16.basename)(file, ".md");
|
|
1729
2336
|
const frontmatter = {
|
|
1730
2337
|
root: false,
|
|
1731
|
-
targets: [
|
|
1732
|
-
description:
|
|
2338
|
+
targets: [config.tool],
|
|
2339
|
+
description: `${config.memoryDescription}: ${filename}`,
|
|
1733
2340
|
globs: ["**/*"]
|
|
1734
2341
|
};
|
|
1735
2342
|
rules.push({
|
|
1736
2343
|
frontmatter,
|
|
1737
2344
|
content: content.trim(),
|
|
1738
|
-
filename:
|
|
2345
|
+
filename: `${config.filenamePrefix}-memory-${filename}`,
|
|
1739
2346
|
filepath: filePath
|
|
1740
2347
|
});
|
|
1741
2348
|
}
|
|
@@ -1745,14 +2352,14 @@ async function parseClaudeMemoryFiles(memoryDir) {
|
|
|
1745
2352
|
}
|
|
1746
2353
|
return rules;
|
|
1747
2354
|
}
|
|
1748
|
-
async function
|
|
2355
|
+
async function parseSettingsFile(settingsPath, tool) {
|
|
1749
2356
|
const errors = [];
|
|
1750
2357
|
let ignorePatterns;
|
|
1751
2358
|
let mcpServers;
|
|
1752
2359
|
try {
|
|
1753
2360
|
const content = await readFileContent(settingsPath);
|
|
1754
2361
|
const settings = JSON.parse(content);
|
|
1755
|
-
if (typeof settings === "object" && settings !== null && "permissions" in settings) {
|
|
2362
|
+
if (tool === "claudecode" && typeof settings === "object" && settings !== null && "permissions" in settings) {
|
|
1756
2363
|
const permissions = settings.permissions;
|
|
1757
2364
|
if (typeof permissions !== "object" || permissions === null) {
|
|
1758
2365
|
return { ignorePatterns: [], errors: [] };
|
|
@@ -1784,151 +2391,62 @@ async function parseClaudeSettings(settingsPath) {
|
|
|
1784
2391
|
};
|
|
1785
2392
|
}
|
|
1786
2393
|
|
|
2394
|
+
// src/parsers/claudecode.ts
|
|
2395
|
+
async function parseClaudeConfiguration(baseDir = process.cwd()) {
|
|
2396
|
+
return parseMemoryBasedConfiguration(baseDir, {
|
|
2397
|
+
tool: "claudecode",
|
|
2398
|
+
mainFileName: "CLAUDE.md",
|
|
2399
|
+
memoryDirPath: ".claude/memories",
|
|
2400
|
+
settingsPath: ".claude/settings.json",
|
|
2401
|
+
mainDescription: "Main Claude Code configuration",
|
|
2402
|
+
memoryDescription: "Memory file",
|
|
2403
|
+
filenamePrefix: "claude"
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
|
|
1787
2407
|
// src/parsers/cline.ts
|
|
1788
|
-
var import_node_path14 = require("path");
|
|
1789
2408
|
async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
};
|
|
1803
|
-
rules.push({
|
|
1804
|
-
frontmatter,
|
|
1805
|
-
content: content.trim(),
|
|
1806
|
-
filename: "cline-instructions",
|
|
1807
|
-
filepath: clineFilePath
|
|
1808
|
-
});
|
|
1809
|
-
}
|
|
1810
|
-
} catch (error) {
|
|
1811
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1812
|
-
errors.push(`Failed to parse .cline/instructions.md: ${errorMessage}`);
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
const clinerulesDirPath = (0, import_node_path14.join)(baseDir, ".clinerules");
|
|
1816
|
-
if (await fileExists(clinerulesDirPath)) {
|
|
1817
|
-
try {
|
|
1818
|
-
const { readdir: readdir2 } = await import("fs/promises");
|
|
1819
|
-
const files = await readdir2(clinerulesDirPath);
|
|
1820
|
-
for (const file of files) {
|
|
1821
|
-
if (file.endsWith(".md")) {
|
|
1822
|
-
const filePath = (0, import_node_path14.join)(clinerulesDirPath, file);
|
|
1823
|
-
try {
|
|
1824
|
-
const content = await readFileContent(filePath);
|
|
1825
|
-
if (content.trim()) {
|
|
1826
|
-
const filename = file.replace(".md", "");
|
|
1827
|
-
const frontmatter = {
|
|
1828
|
-
root: false,
|
|
1829
|
-
targets: ["cline"],
|
|
1830
|
-
description: `Cline rule: ${filename}`,
|
|
1831
|
-
globs: ["**/*"]
|
|
1832
|
-
};
|
|
1833
|
-
rules.push({
|
|
1834
|
-
frontmatter,
|
|
1835
|
-
content: content.trim(),
|
|
1836
|
-
filename: `cline-${filename}`,
|
|
1837
|
-
filepath: filePath
|
|
1838
|
-
});
|
|
1839
|
-
}
|
|
1840
|
-
} catch (error) {
|
|
1841
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1842
|
-
errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
2409
|
+
return parseConfigurationFiles(baseDir, {
|
|
2410
|
+
tool: "cline",
|
|
2411
|
+
mainFile: {
|
|
2412
|
+
path: ".cline/instructions.md",
|
|
2413
|
+
useFrontmatter: false,
|
|
2414
|
+
description: "Cline instructions"
|
|
2415
|
+
},
|
|
2416
|
+
directories: [
|
|
2417
|
+
{
|
|
2418
|
+
directory: ".clinerules",
|
|
2419
|
+
filePattern: ".md",
|
|
2420
|
+
description: "Cline rule"
|
|
1845
2421
|
}
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
if (rules.length === 0) {
|
|
1852
|
-
errors.push("No Cline configuration files found (.cline/instructions.md or .clinerules/*.md)");
|
|
1853
|
-
}
|
|
1854
|
-
return { rules, errors };
|
|
2422
|
+
],
|
|
2423
|
+
errorMessage: "No Cline configuration files found (.cline/instructions.md or .clinerules/*.md)"
|
|
2424
|
+
});
|
|
1855
2425
|
}
|
|
1856
2426
|
|
|
1857
2427
|
// src/parsers/copilot.ts
|
|
1858
|
-
var import_node_path15 = require("path");
|
|
1859
|
-
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
1860
2428
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
description: "GitHub Copilot instructions",
|
|
1874
|
-
globs: ["**/*"]
|
|
1875
|
-
};
|
|
1876
|
-
rules.push({
|
|
1877
|
-
frontmatter,
|
|
1878
|
-
content,
|
|
1879
|
-
filename: "copilot-instructions",
|
|
1880
|
-
filepath: copilotFilePath
|
|
1881
|
-
});
|
|
1882
|
-
}
|
|
1883
|
-
} catch (error) {
|
|
1884
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1885
|
-
errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
|
|
1886
|
-
}
|
|
1887
|
-
}
|
|
1888
|
-
const instructionsDir = (0, import_node_path15.join)(baseDir, ".github", "instructions");
|
|
1889
|
-
if (await fileExists(instructionsDir)) {
|
|
1890
|
-
try {
|
|
1891
|
-
const { readdir: readdir2 } = await import("fs/promises");
|
|
1892
|
-
const files = await readdir2(instructionsDir);
|
|
1893
|
-
for (const file of files) {
|
|
1894
|
-
if (file.endsWith(".instructions.md")) {
|
|
1895
|
-
const filePath = (0, import_node_path15.join)(instructionsDir, file);
|
|
1896
|
-
const rawContent = await readFileContent(filePath);
|
|
1897
|
-
const parsed = (0, import_gray_matter2.default)(rawContent);
|
|
1898
|
-
const content = parsed.content.trim();
|
|
1899
|
-
if (content) {
|
|
1900
|
-
const filename = (0, import_node_path15.basename)(file, ".instructions.md");
|
|
1901
|
-
const frontmatter = {
|
|
1902
|
-
root: false,
|
|
1903
|
-
targets: ["copilot"],
|
|
1904
|
-
description: `Copilot instruction: ${filename}`,
|
|
1905
|
-
globs: ["**/*"]
|
|
1906
|
-
};
|
|
1907
|
-
rules.push({
|
|
1908
|
-
frontmatter,
|
|
1909
|
-
content,
|
|
1910
|
-
filename: `copilot-${filename}`,
|
|
1911
|
-
filepath: filePath
|
|
1912
|
-
});
|
|
1913
|
-
}
|
|
1914
|
-
}
|
|
2429
|
+
return parseConfigurationFiles(baseDir, {
|
|
2430
|
+
tool: "copilot",
|
|
2431
|
+
mainFile: {
|
|
2432
|
+
path: ".github/copilot-instructions.md",
|
|
2433
|
+
useFrontmatter: true,
|
|
2434
|
+
description: "GitHub Copilot instructions"
|
|
2435
|
+
},
|
|
2436
|
+
directories: [
|
|
2437
|
+
{
|
|
2438
|
+
directory: ".github/instructions",
|
|
2439
|
+
filePattern: ".instructions.md",
|
|
2440
|
+
description: "Copilot instruction"
|
|
1915
2441
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
}
|
|
1920
|
-
}
|
|
1921
|
-
if (rules.length === 0) {
|
|
1922
|
-
errors.push(
|
|
1923
|
-
"No Copilot configuration files found (.github/copilot-instructions.md or .github/instructions/*.instructions.md)"
|
|
1924
|
-
);
|
|
1925
|
-
}
|
|
1926
|
-
return { rules, errors };
|
|
2442
|
+
],
|
|
2443
|
+
errorMessage: "No Copilot configuration files found (.github/copilot-instructions.md or .github/instructions/*.instructions.md)"
|
|
2444
|
+
});
|
|
1927
2445
|
}
|
|
1928
2446
|
|
|
1929
2447
|
// src/parsers/cursor.ts
|
|
1930
|
-
var
|
|
1931
|
-
var
|
|
2448
|
+
var import_node_path17 = require("path");
|
|
2449
|
+
var import_gray_matter4 = __toESM(require("gray-matter"), 1);
|
|
1932
2450
|
var import_js_yaml = require("js-yaml");
|
|
1933
2451
|
var import_mini6 = require("zod/mini");
|
|
1934
2452
|
var customMatterOptions = {
|
|
@@ -2052,11 +2570,11 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
2052
2570
|
const rules = [];
|
|
2053
2571
|
let ignorePatterns;
|
|
2054
2572
|
let mcpServers;
|
|
2055
|
-
const cursorFilePath = (0,
|
|
2573
|
+
const cursorFilePath = (0, import_node_path17.join)(baseDir, ".cursorrules");
|
|
2056
2574
|
if (await fileExists(cursorFilePath)) {
|
|
2057
2575
|
try {
|
|
2058
2576
|
const rawContent = await readFileContent(cursorFilePath);
|
|
2059
|
-
const parsed = (0,
|
|
2577
|
+
const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
|
|
2060
2578
|
const content = parsed.content.trim();
|
|
2061
2579
|
if (content) {
|
|
2062
2580
|
const frontmatter = convertCursorMdcFrontmatter(parsed.data, "cursorrules");
|
|
@@ -2073,20 +2591,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
2073
2591
|
errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
|
|
2074
2592
|
}
|
|
2075
2593
|
}
|
|
2076
|
-
const cursorRulesDir = (0,
|
|
2594
|
+
const cursorRulesDir = (0, import_node_path17.join)(baseDir, ".cursor", "rules");
|
|
2077
2595
|
if (await fileExists(cursorRulesDir)) {
|
|
2078
2596
|
try {
|
|
2079
2597
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
2080
2598
|
const files = await readdir2(cursorRulesDir);
|
|
2081
2599
|
for (const file of files) {
|
|
2082
2600
|
if (file.endsWith(".mdc")) {
|
|
2083
|
-
const filePath = (0,
|
|
2601
|
+
const filePath = (0, import_node_path17.join)(cursorRulesDir, file);
|
|
2084
2602
|
try {
|
|
2085
2603
|
const rawContent = await readFileContent(filePath);
|
|
2086
|
-
const parsed = (0,
|
|
2604
|
+
const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
|
|
2087
2605
|
const content = parsed.content.trim();
|
|
2088
2606
|
if (content) {
|
|
2089
|
-
const filename = (0,
|
|
2607
|
+
const filename = (0, import_node_path17.basename)(file, ".mdc");
|
|
2090
2608
|
const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
|
|
2091
2609
|
rules.push({
|
|
2092
2610
|
frontmatter,
|
|
@@ -2109,7 +2627,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
2109
2627
|
if (rules.length === 0) {
|
|
2110
2628
|
errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
|
|
2111
2629
|
}
|
|
2112
|
-
const cursorIgnorePath = (0,
|
|
2630
|
+
const cursorIgnorePath = (0, import_node_path17.join)(baseDir, ".cursorignore");
|
|
2113
2631
|
if (await fileExists(cursorIgnorePath)) {
|
|
2114
2632
|
try {
|
|
2115
2633
|
const content = await readFileContent(cursorIgnorePath);
|
|
@@ -2122,7 +2640,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
2122
2640
|
errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
|
|
2123
2641
|
}
|
|
2124
2642
|
}
|
|
2125
|
-
const cursorMcpPath = (0,
|
|
2643
|
+
const cursorMcpPath = (0, import_node_path17.join)(baseDir, ".cursor", "mcp.json");
|
|
2126
2644
|
if (await fileExists(cursorMcpPath)) {
|
|
2127
2645
|
try {
|
|
2128
2646
|
const content = await readFileContent(cursorMcpPath);
|
|
@@ -2145,134 +2663,6 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
2145
2663
|
}
|
|
2146
2664
|
|
|
2147
2665
|
// src/parsers/geminicli.ts
|
|
2148
|
-
var import_node_path17 = require("path");
|
|
2149
|
-
async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
2150
|
-
const errors = [];
|
|
2151
|
-
const rules = [];
|
|
2152
|
-
let ignorePatterns;
|
|
2153
|
-
let mcpServers;
|
|
2154
|
-
const geminiFilePath = (0, import_node_path17.join)(baseDir, "GEMINI.md");
|
|
2155
|
-
if (!await fileExists(geminiFilePath)) {
|
|
2156
|
-
errors.push("GEMINI.md file not found");
|
|
2157
|
-
return { rules, errors };
|
|
2158
|
-
}
|
|
2159
|
-
try {
|
|
2160
|
-
const geminiContent = await readFileContent(geminiFilePath);
|
|
2161
|
-
const mainRule = parseGeminiMainFile(geminiContent, geminiFilePath);
|
|
2162
|
-
if (mainRule) {
|
|
2163
|
-
rules.push(mainRule);
|
|
2164
|
-
}
|
|
2165
|
-
const memoryDir = (0, import_node_path17.join)(baseDir, ".gemini", "memories");
|
|
2166
|
-
if (await fileExists(memoryDir)) {
|
|
2167
|
-
const memoryRules = await parseGeminiMemoryFiles(memoryDir);
|
|
2168
|
-
rules.push(...memoryRules);
|
|
2169
|
-
}
|
|
2170
|
-
const settingsPath = (0, import_node_path17.join)(baseDir, ".gemini", "settings.json");
|
|
2171
|
-
if (await fileExists(settingsPath)) {
|
|
2172
|
-
const settingsResult = await parseGeminiSettings(settingsPath);
|
|
2173
|
-
if (settingsResult.ignorePatterns) {
|
|
2174
|
-
ignorePatterns = settingsResult.ignorePatterns;
|
|
2175
|
-
}
|
|
2176
|
-
if (settingsResult.mcpServers) {
|
|
2177
|
-
mcpServers = settingsResult.mcpServers;
|
|
2178
|
-
}
|
|
2179
|
-
errors.push(...settingsResult.errors);
|
|
2180
|
-
}
|
|
2181
|
-
const aiexcludePath = (0, import_node_path17.join)(baseDir, ".aiexclude");
|
|
2182
|
-
if (await fileExists(aiexcludePath)) {
|
|
2183
|
-
const aiexcludePatterns = await parseAiexclude(aiexcludePath);
|
|
2184
|
-
if (aiexcludePatterns.length > 0) {
|
|
2185
|
-
ignorePatterns = ignorePatterns ? [...ignorePatterns, ...aiexcludePatterns] : aiexcludePatterns;
|
|
2186
|
-
}
|
|
2187
|
-
}
|
|
2188
|
-
} catch (error) {
|
|
2189
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2190
|
-
errors.push(`Failed to parse Gemini configuration: ${errorMessage}`);
|
|
2191
|
-
}
|
|
2192
|
-
return {
|
|
2193
|
-
rules,
|
|
2194
|
-
errors,
|
|
2195
|
-
...ignorePatterns && { ignorePatterns },
|
|
2196
|
-
...mcpServers && { mcpServers }
|
|
2197
|
-
};
|
|
2198
|
-
}
|
|
2199
|
-
function parseGeminiMainFile(content, filepath) {
|
|
2200
|
-
const lines = content.split("\n");
|
|
2201
|
-
let contentStartIndex = 0;
|
|
2202
|
-
if (lines.some((line) => line.includes("| Document | Description | File Patterns |"))) {
|
|
2203
|
-
const tableEndIndex = lines.findIndex(
|
|
2204
|
-
(line, index) => index > 0 && line.trim() === "" && lines[index - 1]?.includes("|") && !lines[index + 1]?.includes("|")
|
|
2205
|
-
);
|
|
2206
|
-
if (tableEndIndex !== -1) {
|
|
2207
|
-
contentStartIndex = tableEndIndex + 1;
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
const mainContent = lines.slice(contentStartIndex).join("\n").trim();
|
|
2211
|
-
if (!mainContent) {
|
|
2212
|
-
return null;
|
|
2213
|
-
}
|
|
2214
|
-
const frontmatter = {
|
|
2215
|
-
root: false,
|
|
2216
|
-
targets: ["geminicli"],
|
|
2217
|
-
description: "Main Gemini CLI configuration",
|
|
2218
|
-
globs: ["**/*"]
|
|
2219
|
-
};
|
|
2220
|
-
return {
|
|
2221
|
-
frontmatter,
|
|
2222
|
-
content: mainContent,
|
|
2223
|
-
filename: "gemini-main",
|
|
2224
|
-
filepath
|
|
2225
|
-
};
|
|
2226
|
-
}
|
|
2227
|
-
async function parseGeminiMemoryFiles(memoryDir) {
|
|
2228
|
-
const rules = [];
|
|
2229
|
-
try {
|
|
2230
|
-
const { readdir: readdir2 } = await import("fs/promises");
|
|
2231
|
-
const files = await readdir2(memoryDir);
|
|
2232
|
-
for (const file of files) {
|
|
2233
|
-
if (file.endsWith(".md")) {
|
|
2234
|
-
const filePath = (0, import_node_path17.join)(memoryDir, file);
|
|
2235
|
-
const content = await readFileContent(filePath);
|
|
2236
|
-
if (content.trim()) {
|
|
2237
|
-
const filename = (0, import_node_path17.basename)(file, ".md");
|
|
2238
|
-
const frontmatter = {
|
|
2239
|
-
root: false,
|
|
2240
|
-
targets: ["geminicli"],
|
|
2241
|
-
description: `Memory file: ${filename}`,
|
|
2242
|
-
globs: ["**/*"]
|
|
2243
|
-
};
|
|
2244
|
-
rules.push({
|
|
2245
|
-
frontmatter,
|
|
2246
|
-
content: content.trim(),
|
|
2247
|
-
filename: `gemini-memory-${filename}`,
|
|
2248
|
-
filepath: filePath
|
|
2249
|
-
});
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
}
|
|
2253
|
-
} catch {
|
|
2254
|
-
}
|
|
2255
|
-
return rules;
|
|
2256
|
-
}
|
|
2257
|
-
async function parseGeminiSettings(settingsPath) {
|
|
2258
|
-
const errors = [];
|
|
2259
|
-
let mcpServers;
|
|
2260
|
-
try {
|
|
2261
|
-
const content = await readFileContent(settingsPath);
|
|
2262
|
-
const settings = JSON.parse(content);
|
|
2263
|
-
const parseResult = RulesyncMcpConfigSchema.safeParse(settings);
|
|
2264
|
-
if (parseResult.success && Object.keys(parseResult.data.mcpServers).length > 0) {
|
|
2265
|
-
mcpServers = parseResult.data.mcpServers;
|
|
2266
|
-
}
|
|
2267
|
-
} catch (error) {
|
|
2268
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2269
|
-
errors.push(`Failed to parse settings.json: ${errorMessage}`);
|
|
2270
|
-
}
|
|
2271
|
-
return {
|
|
2272
|
-
errors,
|
|
2273
|
-
...mcpServers && { mcpServers }
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
2666
|
async function parseAiexclude(aiexcludePath) {
|
|
2277
2667
|
try {
|
|
2278
2668
|
const content = await readFileContent(aiexcludePath);
|
|
@@ -2282,75 +2672,40 @@ async function parseAiexclude(aiexcludePath) {
|
|
|
2282
2672
|
return [];
|
|
2283
2673
|
}
|
|
2284
2674
|
}
|
|
2675
|
+
async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
2676
|
+
return parseMemoryBasedConfiguration(baseDir, {
|
|
2677
|
+
tool: "geminicli",
|
|
2678
|
+
mainFileName: "GEMINI.md",
|
|
2679
|
+
memoryDirPath: ".gemini/memories",
|
|
2680
|
+
settingsPath: ".gemini/settings.json",
|
|
2681
|
+
mainDescription: "Main Gemini CLI configuration",
|
|
2682
|
+
memoryDescription: "Memory file",
|
|
2683
|
+
filenamePrefix: "gemini",
|
|
2684
|
+
additionalIgnoreFile: {
|
|
2685
|
+
path: ".aiexclude",
|
|
2686
|
+
parser: parseAiexclude
|
|
2687
|
+
}
|
|
2688
|
+
});
|
|
2689
|
+
}
|
|
2285
2690
|
|
|
2286
2691
|
// src/parsers/roo.ts
|
|
2287
|
-
var import_node_path18 = require("path");
|
|
2288
2692
|
async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
};
|
|
2302
|
-
rules.push({
|
|
2303
|
-
frontmatter,
|
|
2304
|
-
content: content.trim(),
|
|
2305
|
-
filename: "roo-instructions",
|
|
2306
|
-
filepath: rooFilePath
|
|
2307
|
-
});
|
|
2308
|
-
}
|
|
2309
|
-
} catch (error) {
|
|
2310
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2311
|
-
errors.push(`Failed to parse .roo/instructions.md: ${errorMessage}`);
|
|
2312
|
-
}
|
|
2313
|
-
}
|
|
2314
|
-
const rooRulesDir = (0, import_node_path18.join)(baseDir, ".roo", "rules");
|
|
2315
|
-
if (await fileExists(rooRulesDir)) {
|
|
2316
|
-
try {
|
|
2317
|
-
const { readdir: readdir2 } = await import("fs/promises");
|
|
2318
|
-
const files = await readdir2(rooRulesDir);
|
|
2319
|
-
for (const file of files) {
|
|
2320
|
-
if (file.endsWith(".md")) {
|
|
2321
|
-
const filePath = (0, import_node_path18.join)(rooRulesDir, file);
|
|
2322
|
-
try {
|
|
2323
|
-
const content = await readFileContent(filePath);
|
|
2324
|
-
if (content.trim()) {
|
|
2325
|
-
const filename = file.replace(".md", "");
|
|
2326
|
-
const frontmatter = {
|
|
2327
|
-
root: false,
|
|
2328
|
-
targets: ["roo"],
|
|
2329
|
-
description: `Roo rule: ${filename}`,
|
|
2330
|
-
globs: ["**/*"]
|
|
2331
|
-
};
|
|
2332
|
-
rules.push({
|
|
2333
|
-
frontmatter,
|
|
2334
|
-
content: content.trim(),
|
|
2335
|
-
filename: `roo-${filename}`,
|
|
2336
|
-
filepath: filePath
|
|
2337
|
-
});
|
|
2338
|
-
}
|
|
2339
|
-
} catch (error) {
|
|
2340
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2341
|
-
errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
|
|
2342
|
-
}
|
|
2343
|
-
}
|
|
2693
|
+
return parseConfigurationFiles(baseDir, {
|
|
2694
|
+
tool: "roo",
|
|
2695
|
+
mainFile: {
|
|
2696
|
+
path: ".roo/instructions.md",
|
|
2697
|
+
useFrontmatter: false,
|
|
2698
|
+
description: "Roo Code instructions"
|
|
2699
|
+
},
|
|
2700
|
+
directories: [
|
|
2701
|
+
{
|
|
2702
|
+
directory: ".roo/rules",
|
|
2703
|
+
filePattern: ".md",
|
|
2704
|
+
description: "Roo rule"
|
|
2344
2705
|
}
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
}
|
|
2349
|
-
}
|
|
2350
|
-
if (rules.length === 0) {
|
|
2351
|
-
errors.push("No Roo Code configuration files found (.roo/instructions.md or .roo/rules/*.md)");
|
|
2352
|
-
}
|
|
2353
|
-
return { rules, errors };
|
|
2706
|
+
],
|
|
2707
|
+
errorMessage: "No Roo Code configuration files found (.roo/instructions.md or .roo/rules/*.md)"
|
|
2708
|
+
});
|
|
2354
2709
|
}
|
|
2355
2710
|
|
|
2356
2711
|
// src/core/importer.ts
|
|
@@ -2365,6 +2720,18 @@ async function importConfiguration(options) {
|
|
|
2365
2720
|
}
|
|
2366
2721
|
try {
|
|
2367
2722
|
switch (tool) {
|
|
2723
|
+
case "augmentcode": {
|
|
2724
|
+
const augmentResult = await parseAugmentcodeConfiguration(baseDir);
|
|
2725
|
+
rules = augmentResult.rules;
|
|
2726
|
+
errors.push(...augmentResult.errors);
|
|
2727
|
+
break;
|
|
2728
|
+
}
|
|
2729
|
+
case "augmentcode-legacy": {
|
|
2730
|
+
const augmentLegacyResult = await parseAugmentcodeLegacyConfiguration(baseDir);
|
|
2731
|
+
rules = augmentLegacyResult.rules;
|
|
2732
|
+
errors.push(...augmentLegacyResult.errors);
|
|
2733
|
+
break;
|
|
2734
|
+
}
|
|
2368
2735
|
case "claudecode": {
|
|
2369
2736
|
const claudeResult = await parseClaudeConfiguration(baseDir);
|
|
2370
2737
|
rules = claudeResult.rules;
|
|
@@ -2419,7 +2786,7 @@ async function importConfiguration(options) {
|
|
|
2419
2786
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
2420
2787
|
return { success: false, rulesCreated: 0, errors };
|
|
2421
2788
|
}
|
|
2422
|
-
const rulesDirPath = (0,
|
|
2789
|
+
const rulesDirPath = (0, import_node_path18.join)(baseDir, rulesDir);
|
|
2423
2790
|
try {
|
|
2424
2791
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
2425
2792
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -2433,7 +2800,7 @@ async function importConfiguration(options) {
|
|
|
2433
2800
|
try {
|
|
2434
2801
|
const baseFilename = `${tool}__${rule.filename}`;
|
|
2435
2802
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
2436
|
-
const filePath = (0,
|
|
2803
|
+
const filePath = (0, import_node_path18.join)(rulesDirPath, `${filename}.md`);
|
|
2437
2804
|
const content = generateRuleFileContent(rule);
|
|
2438
2805
|
await writeFileContent(filePath, content);
|
|
2439
2806
|
rulesCreated++;
|
|
@@ -2448,7 +2815,7 @@ async function importConfiguration(options) {
|
|
|
2448
2815
|
let ignoreFileCreated = false;
|
|
2449
2816
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
2450
2817
|
try {
|
|
2451
|
-
const rulesyncignorePath = (0,
|
|
2818
|
+
const rulesyncignorePath = (0, import_node_path18.join)(baseDir, ".rulesyncignore");
|
|
2452
2819
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
2453
2820
|
`;
|
|
2454
2821
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -2464,7 +2831,7 @@ async function importConfiguration(options) {
|
|
|
2464
2831
|
let mcpFileCreated = false;
|
|
2465
2832
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
2466
2833
|
try {
|
|
2467
|
-
const mcpPath = (0,
|
|
2834
|
+
const mcpPath = (0, import_node_path18.join)(baseDir, rulesDir, ".mcp.json");
|
|
2468
2835
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
2469
2836
|
`;
|
|
2470
2837
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -2486,13 +2853,13 @@ async function importConfiguration(options) {
|
|
|
2486
2853
|
};
|
|
2487
2854
|
}
|
|
2488
2855
|
function generateRuleFileContent(rule) {
|
|
2489
|
-
const frontmatter =
|
|
2856
|
+
const frontmatter = import_gray_matter5.default.stringify("", rule.frontmatter);
|
|
2490
2857
|
return frontmatter + rule.content;
|
|
2491
2858
|
}
|
|
2492
2859
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
2493
2860
|
let filename = baseFilename;
|
|
2494
2861
|
let counter = 1;
|
|
2495
|
-
while (await fileExists((0,
|
|
2862
|
+
while (await fileExists((0, import_node_path18.join)(rulesDir, `${filename}.md`))) {
|
|
2496
2863
|
filename = `${baseFilename}-${counter}`;
|
|
2497
2864
|
counter++;
|
|
2498
2865
|
}
|
|
@@ -2502,6 +2869,8 @@ async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
|
2502
2869
|
// src/cli/commands/import.ts
|
|
2503
2870
|
async function importCommand(options = {}) {
|
|
2504
2871
|
const tools = [];
|
|
2872
|
+
if (options.augmentcode) tools.push("augmentcode");
|
|
2873
|
+
if (options.augmentcodeLegacy) tools.push("augmentcode-legacy");
|
|
2505
2874
|
if (options.claudecode) tools.push("claudecode");
|
|
2506
2875
|
if (options.cursor) tools.push("cursor");
|
|
2507
2876
|
if (options.copilot) tools.push("copilot");
|
|
@@ -2510,7 +2879,7 @@ async function importCommand(options = {}) {
|
|
|
2510
2879
|
if (options.geminicli) tools.push("geminicli");
|
|
2511
2880
|
if (tools.length === 0) {
|
|
2512
2881
|
console.error(
|
|
2513
|
-
"\u274C Please specify one tool to import from (--claudecode, --cursor, --copilot, --cline, --roo, --geminicli)"
|
|
2882
|
+
"\u274C Please specify one tool to import from (--augmentcode, --augmentcodeLegacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli)"
|
|
2514
2883
|
);
|
|
2515
2884
|
process.exit(1);
|
|
2516
2885
|
}
|
|
@@ -2557,7 +2926,7 @@ async function importCommand(options = {}) {
|
|
|
2557
2926
|
}
|
|
2558
2927
|
|
|
2559
2928
|
// src/cli/commands/init.ts
|
|
2560
|
-
var
|
|
2929
|
+
var import_node_path19 = require("path");
|
|
2561
2930
|
async function initCommand() {
|
|
2562
2931
|
const aiRulesDir = ".rulesync";
|
|
2563
2932
|
console.log("Initializing rulesync...");
|
|
@@ -2604,7 +2973,7 @@ globs: ["**/*"]
|
|
|
2604
2973
|
- Follow single responsibility principle
|
|
2605
2974
|
`
|
|
2606
2975
|
};
|
|
2607
|
-
const filepath = (0,
|
|
2976
|
+
const filepath = (0, import_node_path19.join)(aiRulesDir, sampleFile.filename);
|
|
2608
2977
|
if (!await fileExists(filepath)) {
|
|
2609
2978
|
await writeFileContent(filepath, sampleFile.content);
|
|
2610
2979
|
console.log(`Created ${filepath}`);
|
|
@@ -2748,16 +3117,18 @@ async function watchCommand() {
|
|
|
2748
3117
|
|
|
2749
3118
|
// src/cli/index.ts
|
|
2750
3119
|
var program = new import_commander.Command();
|
|
2751
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
3120
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.49.0");
|
|
2752
3121
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
2753
3122
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
2754
3123
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|
|
2755
|
-
program.command("import").description("Import configurations from AI tools to rulesync format").option("--claudecode", "Import from Claude Code (CLAUDE.md)").option("--cursor", "Import from Cursor (.cursorrules)").option("--copilot", "Import from GitHub Copilot (.github/copilot-instructions.md)").option("--cline", "Import from Cline (.cline/instructions.md)").option("--roo", "Import from Roo Code (.roo/instructions.md)").option("--geminicli", "Import from Gemini CLI (GEMINI.md)").option("-v, --verbose", "Verbose output").action(importCommand);
|
|
2756
|
-
program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--kiro", "Generate only for Kiro IDE").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
3124
|
+
program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--augmentcodeLegacy", "Import from AugmentCode legacy format (.augment-guidelines)").option("--claudecode", "Import from Claude Code (CLAUDE.md)").option("--cursor", "Import from Cursor (.cursorrules)").option("--copilot", "Import from GitHub Copilot (.github/copilot-instructions.md)").option("--cline", "Import from Cline (.cline/instructions.md)").option("--roo", "Import from Roo Code (.roo/instructions.md)").option("--geminicli", "Import from Gemini CLI (GEMINI.md)").option("-v, --verbose", "Verbose output").action(importCommand);
|
|
3125
|
+
program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcodeLegacy", "Generate only for AugmentCode legacy format").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--kiro", "Generate only for Kiro IDE").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
2757
3126
|
"-b, --base-dir <paths>",
|
|
2758
3127
|
"Base directories to generate files (comma-separated for multiple paths)"
|
|
2759
3128
|
).option("-v, --verbose", "Verbose output").action(async (options) => {
|
|
2760
3129
|
const tools = [];
|
|
3130
|
+
if (options.augmentcode) tools.push("augmentcode");
|
|
3131
|
+
if (options.augmentcodeLegacy) tools.push("augmentcode-legacy");
|
|
2761
3132
|
if (options.copilot) tools.push("copilot");
|
|
2762
3133
|
if (options.cursor) tools.push("cursor");
|
|
2763
3134
|
if (options.cline) tools.push("cline");
|