rulesync 0.48.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/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: ["copilot", "cursor", "cline", "claudecode", "roo", "geminicli", "kiro"]
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/kiro.ts
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, import_node_path.join)(outputPath, ".aiignore");
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 = extractIgnorePatternsFromRules(rules);
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 extractIgnorePatternsFromRules(rules) {
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/claudecode.ts
586
- var import_node_path4 = require("path");
861
+ // src/generators/rules/augmentcode.ts
862
+ var import_node_path6 = require("path");
587
863
 
588
- // src/types/claudecode.ts
589
- var import_mini2 = require("zod/mini");
590
- var ClaudeSettingsSchema = import_mini2.z.looseObject({
591
- permissions: import_mini2.z._default(
592
- import_mini2.z.looseObject({
593
- deny: import_mini2.z._default(import_mini2.z.array(import_mini2.z.string()), [])
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 import_node_path2 = require("path");
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, import_node_path2.dirname)(filepath));
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, import_node_path2.join)(dir, file));
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, import_node_path3.join)(baseDir, ".rulesyncignore");
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, import_node_path4.join)(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
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, import_node_path4.join)(claudeOutputDir, "CLAUDE.md"),
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, import_node_path4.join)(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
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, import_node_path4.join)(baseDir, ".claude", "settings.json") : (0, import_node_path4.join)(".claude", "settings.json");
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
- const outputs = [];
806
- for (const rule of rules) {
807
- const content = generateClineMarkdown(rule);
808
- const outputDir = baseDir ? (0, import_node_path5.join)(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
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
- filepath: clineIgnorePath,
823
- content: clineIgnoreContent
824
- });
825
- }
826
- return outputs;
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 import_node_path6 = require("path");
1226
+ var import_node_path8 = require("path");
843
1227
  async function generateCopilotConfig(rules, config, baseDir) {
844
- const outputs = [];
845
- for (const rule of rules) {
846
- const content = generateCopilotMarkdown(rule);
847
- const baseFilename = rule.filename.replace(/\.md$/, "");
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
- filepath: copilotIgnorePath,
863
- content: copilotIgnoreContent
864
- });
865
- }
866
- return outputs;
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 import_node_path7 = require("path");
1259
+ var import_node_path9 = require("path");
895
1260
  async function generateCursorConfig(rules, config, baseDir) {
896
- const outputs = [];
897
- for (const rule of rules) {
898
- const content = generateCursorMarkdown(rule);
899
- const outputDir = baseDir ? (0, import_node_path7.join)(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
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
- filepath: cursorIgnorePath,
914
- content: cursorIgnoreContent
915
- });
916
- }
917
- return outputs;
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 import_node_path8 = require("path");
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, import_node_path8.join)(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
990
- const filepath = (0, import_node_path8.join)(outputDir, `${rule.filename}.md`);
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, import_node_path8.join)(baseDir, "GEMINI.md") : "GEMINI.md";
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, import_node_path8.join)(baseDir, ".aiexclude") : ".aiexclude";
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 import_node_path9 = require("path");
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, import_node_path9.join)(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
1060
- const filepath = (0, import_node_path9.join)(outputDir, `${rule.filename}.md`);
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
- const outputs = [];
1077
- for (const rule of rules) {
1078
- const content = generateRooMarkdown(rule);
1079
- const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
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
- filepath: rooIgnorePath,
1094
- content: rooIgnoreContent
1095
- });
1096
- }
1097
- return outputs;
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 import_node_path11 = require("path");
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, import_node_path11.basename)(filepath, ".md");
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,
@@ -1588,9 +1938,9 @@ Generating configurations for base directory: ${baseDir}`);
1588
1938
 
1589
1939
  // src/cli/commands/gitignore.ts
1590
1940
  var import_node_fs = require("fs");
1591
- var import_node_path12 = require("path");
1941
+ var import_node_path13 = require("path");
1592
1942
  var gitignoreCommand = async () => {
1593
- const gitignorePath = (0, import_node_path12.join)(process.cwd(), ".gitignore");
1943
+ const gitignorePath = (0, import_node_path13.join)(process.cwd(), ".gitignore");
1594
1944
  const rulesFilesToIgnore = [
1595
1945
  "# Generated by rulesync - AI tool configuration files",
1596
1946
  "**/.github/copilot-instructions.md",
@@ -1608,7 +1958,10 @@ var gitignoreCommand = async () => {
1608
1958
  "**/.gemini/memories/",
1609
1959
  "**/.aiexclude",
1610
1960
  "**/.aiignore",
1961
+ "**/.augmentignore",
1611
1962
  "**/.kiro/steering/",
1963
+ "**/.augment/rules/",
1964
+ "**/.augment-guidelines",
1612
1965
  "**/.mcp.json",
1613
1966
  "!.rulesync/.mcp.json",
1614
1967
  "**/.cursor/mcp.json",
@@ -1646,35 +1999,273 @@ ${linesToAdd.join("\n")}
1646
1999
  };
1647
2000
 
1648
2001
  // src/core/importer.ts
1649
- var import_node_path19 = require("path");
1650
- var import_gray_matter4 = __toESM(require("gray-matter"), 1);
2002
+ var import_node_path18 = require("path");
2003
+ var import_gray_matter5 = __toESM(require("gray-matter"), 1);
1651
2004
 
1652
- // src/parsers/claudecode.ts
1653
- var import_node_path13 = require("path");
1654
- async function parseClaudeConfiguration(baseDir = process.cwd()) {
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) {
1655
2246
  const errors = [];
1656
2247
  const rules = [];
1657
2248
  let ignorePatterns;
1658
2249
  let mcpServers;
1659
- const claudeFilePath = (0, import_node_path13.join)(baseDir, "CLAUDE.md");
1660
- if (!await fileExists(claudeFilePath)) {
1661
- errors.push("CLAUDE.md file not found");
2250
+ const mainFilePath = (0, import_node_path16.join)(baseDir, config.mainFileName);
2251
+ if (!await fileExists(mainFilePath)) {
2252
+ errors.push(`${config.mainFileName} file not found`);
1662
2253
  return { rules, errors };
1663
2254
  }
1664
2255
  try {
1665
- const claudeContent = await readFileContent(claudeFilePath);
1666
- const mainRule = parseClaudeMainFile(claudeContent, claudeFilePath);
2256
+ const mainContent = await readFileContent(mainFilePath);
2257
+ const mainRule = parseMainFile(mainContent, mainFilePath, config);
1667
2258
  if (mainRule) {
1668
2259
  rules.push(mainRule);
1669
2260
  }
1670
- const memoryDir = (0, import_node_path13.join)(baseDir, ".claude", "memories");
2261
+ const memoryDir = (0, import_node_path16.join)(baseDir, config.memoryDirPath);
1671
2262
  if (await fileExists(memoryDir)) {
1672
- const memoryRules = await parseClaudeMemoryFiles(memoryDir);
2263
+ const memoryRules = await parseMemoryFiles(memoryDir, config);
1673
2264
  rules.push(...memoryRules);
1674
2265
  }
1675
- const settingsPath = (0, import_node_path13.join)(baseDir, ".claude", "settings.json");
2266
+ const settingsPath = (0, import_node_path16.join)(baseDir, config.settingsPath);
1676
2267
  if (await fileExists(settingsPath)) {
1677
- const settingsResult = await parseClaudeSettings(settingsPath);
2268
+ const settingsResult = await parseSettingsFile(settingsPath, config.tool);
1678
2269
  if (settingsResult.ignorePatterns) {
1679
2270
  ignorePatterns = settingsResult.ignorePatterns;
1680
2271
  }
@@ -1683,9 +2274,18 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
1683
2274
  }
1684
2275
  errors.push(...settingsResult.errors);
1685
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
+ }
1686
2286
  } catch (error) {
1687
2287
  const errorMessage = error instanceof Error ? error.message : String(error);
1688
- errors.push(`Failed to parse Claude configuration: ${errorMessage}`);
2288
+ errors.push(`Failed to parse ${config.tool} configuration: ${errorMessage}`);
1689
2289
  }
1690
2290
  return {
1691
2291
  rules,
@@ -1694,7 +2294,7 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
1694
2294
  ...mcpServers && { mcpServers }
1695
2295
  };
1696
2296
  }
1697
- function parseClaudeMainFile(content, filepath) {
2297
+ function parseMainFile(content, filepath, config) {
1698
2298
  const lines = content.split("\n");
1699
2299
  let contentStartIndex = 0;
1700
2300
  if (lines.some((line) => line.includes("| Document | Description | File Patterns |"))) {
@@ -1711,38 +2311,38 @@ function parseClaudeMainFile(content, filepath) {
1711
2311
  }
1712
2312
  const frontmatter = {
1713
2313
  root: false,
1714
- targets: ["claudecode"],
1715
- description: "Main Claude Code configuration",
2314
+ targets: [config.tool],
2315
+ description: config.mainDescription,
1716
2316
  globs: ["**/*"]
1717
2317
  };
1718
2318
  return {
1719
2319
  frontmatter,
1720
2320
  content: mainContent,
1721
- filename: "claude-main",
2321
+ filename: `${config.filenamePrefix}-main`,
1722
2322
  filepath
1723
2323
  };
1724
2324
  }
1725
- async function parseClaudeMemoryFiles(memoryDir) {
2325
+ async function parseMemoryFiles(memoryDir, config) {
1726
2326
  const rules = [];
1727
2327
  try {
1728
2328
  const { readdir: readdir2 } = await import("fs/promises");
1729
2329
  const files = await readdir2(memoryDir);
1730
2330
  for (const file of files) {
1731
2331
  if (file.endsWith(".md")) {
1732
- const filePath = (0, import_node_path13.join)(memoryDir, file);
2332
+ const filePath = (0, import_node_path16.join)(memoryDir, file);
1733
2333
  const content = await readFileContent(filePath);
1734
2334
  if (content.trim()) {
1735
- const filename = (0, import_node_path13.basename)(file, ".md");
2335
+ const filename = (0, import_node_path16.basename)(file, ".md");
1736
2336
  const frontmatter = {
1737
2337
  root: false,
1738
- targets: ["claudecode"],
1739
- description: `Memory file: ${filename}`,
2338
+ targets: [config.tool],
2339
+ description: `${config.memoryDescription}: ${filename}`,
1740
2340
  globs: ["**/*"]
1741
2341
  };
1742
2342
  rules.push({
1743
2343
  frontmatter,
1744
2344
  content: content.trim(),
1745
- filename: `claude-memory-${filename}`,
2345
+ filename: `${config.filenamePrefix}-memory-${filename}`,
1746
2346
  filepath: filePath
1747
2347
  });
1748
2348
  }
@@ -1752,14 +2352,14 @@ async function parseClaudeMemoryFiles(memoryDir) {
1752
2352
  }
1753
2353
  return rules;
1754
2354
  }
1755
- async function parseClaudeSettings(settingsPath) {
2355
+ async function parseSettingsFile(settingsPath, tool) {
1756
2356
  const errors = [];
1757
2357
  let ignorePatterns;
1758
2358
  let mcpServers;
1759
2359
  try {
1760
2360
  const content = await readFileContent(settingsPath);
1761
2361
  const settings = JSON.parse(content);
1762
- if (typeof settings === "object" && settings !== null && "permissions" in settings) {
2362
+ if (tool === "claudecode" && typeof settings === "object" && settings !== null && "permissions" in settings) {
1763
2363
  const permissions = settings.permissions;
1764
2364
  if (typeof permissions !== "object" || permissions === null) {
1765
2365
  return { ignorePatterns: [], errors: [] };
@@ -1791,151 +2391,62 @@ async function parseClaudeSettings(settingsPath) {
1791
2391
  };
1792
2392
  }
1793
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
+
1794
2407
  // src/parsers/cline.ts
1795
- var import_node_path14 = require("path");
1796
2408
  async function parseClineConfiguration(baseDir = process.cwd()) {
1797
- const errors = [];
1798
- const rules = [];
1799
- const clineFilePath = (0, import_node_path14.join)(baseDir, ".cline", "instructions.md");
1800
- if (await fileExists(clineFilePath)) {
1801
- try {
1802
- const content = await readFileContent(clineFilePath);
1803
- if (content.trim()) {
1804
- const frontmatter = {
1805
- root: false,
1806
- targets: ["cline"],
1807
- description: "Cline instructions",
1808
- globs: ["**/*"]
1809
- };
1810
- rules.push({
1811
- frontmatter,
1812
- content: content.trim(),
1813
- filename: "cline-instructions",
1814
- filepath: clineFilePath
1815
- });
1816
- }
1817
- } catch (error) {
1818
- const errorMessage = error instanceof Error ? error.message : String(error);
1819
- errors.push(`Failed to parse .cline/instructions.md: ${errorMessage}`);
1820
- }
1821
- }
1822
- const clinerulesDirPath = (0, import_node_path14.join)(baseDir, ".clinerules");
1823
- if (await fileExists(clinerulesDirPath)) {
1824
- try {
1825
- const { readdir: readdir2 } = await import("fs/promises");
1826
- const files = await readdir2(clinerulesDirPath);
1827
- for (const file of files) {
1828
- if (file.endsWith(".md")) {
1829
- const filePath = (0, import_node_path14.join)(clinerulesDirPath, file);
1830
- try {
1831
- const content = await readFileContent(filePath);
1832
- if (content.trim()) {
1833
- const filename = file.replace(".md", "");
1834
- const frontmatter = {
1835
- root: false,
1836
- targets: ["cline"],
1837
- description: `Cline rule: ${filename}`,
1838
- globs: ["**/*"]
1839
- };
1840
- rules.push({
1841
- frontmatter,
1842
- content: content.trim(),
1843
- filename: `cline-${filename}`,
1844
- filepath: filePath
1845
- });
1846
- }
1847
- } catch (error) {
1848
- const errorMessage = error instanceof Error ? error.message : String(error);
1849
- errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
1850
- }
1851
- }
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"
1852
2421
  }
1853
- } catch (error) {
1854
- const errorMessage = error instanceof Error ? error.message : String(error);
1855
- errors.push(`Failed to parse .clinerules files: ${errorMessage}`);
1856
- }
1857
- }
1858
- if (rules.length === 0) {
1859
- errors.push("No Cline configuration files found (.cline/instructions.md or .clinerules/*.md)");
1860
- }
1861
- return { rules, errors };
2422
+ ],
2423
+ errorMessage: "No Cline configuration files found (.cline/instructions.md or .clinerules/*.md)"
2424
+ });
1862
2425
  }
1863
2426
 
1864
2427
  // src/parsers/copilot.ts
1865
- var import_node_path15 = require("path");
1866
- var import_gray_matter2 = __toESM(require("gray-matter"), 1);
1867
2428
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
1868
- const errors = [];
1869
- const rules = [];
1870
- const copilotFilePath = (0, import_node_path15.join)(baseDir, ".github", "copilot-instructions.md");
1871
- if (await fileExists(copilotFilePath)) {
1872
- try {
1873
- const rawContent = await readFileContent(copilotFilePath);
1874
- const parsed = (0, import_gray_matter2.default)(rawContent);
1875
- const content = parsed.content.trim();
1876
- if (content) {
1877
- const frontmatter = {
1878
- root: false,
1879
- targets: ["copilot"],
1880
- description: "GitHub Copilot instructions",
1881
- globs: ["**/*"]
1882
- };
1883
- rules.push({
1884
- frontmatter,
1885
- content,
1886
- filename: "copilot-instructions",
1887
- filepath: copilotFilePath
1888
- });
1889
- }
1890
- } catch (error) {
1891
- const errorMessage = error instanceof Error ? error.message : String(error);
1892
- errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
1893
- }
1894
- }
1895
- const instructionsDir = (0, import_node_path15.join)(baseDir, ".github", "instructions");
1896
- if (await fileExists(instructionsDir)) {
1897
- try {
1898
- const { readdir: readdir2 } = await import("fs/promises");
1899
- const files = await readdir2(instructionsDir);
1900
- for (const file of files) {
1901
- if (file.endsWith(".instructions.md")) {
1902
- const filePath = (0, import_node_path15.join)(instructionsDir, file);
1903
- const rawContent = await readFileContent(filePath);
1904
- const parsed = (0, import_gray_matter2.default)(rawContent);
1905
- const content = parsed.content.trim();
1906
- if (content) {
1907
- const filename = (0, import_node_path15.basename)(file, ".instructions.md");
1908
- const frontmatter = {
1909
- root: false,
1910
- targets: ["copilot"],
1911
- description: `Copilot instruction: ${filename}`,
1912
- globs: ["**/*"]
1913
- };
1914
- rules.push({
1915
- frontmatter,
1916
- content,
1917
- filename: `copilot-${filename}`,
1918
- filepath: filePath
1919
- });
1920
- }
1921
- }
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"
1922
2441
  }
1923
- } catch (error) {
1924
- const errorMessage = error instanceof Error ? error.message : String(error);
1925
- errors.push(`Failed to parse .github/instructions files: ${errorMessage}`);
1926
- }
1927
- }
1928
- if (rules.length === 0) {
1929
- errors.push(
1930
- "No Copilot configuration files found (.github/copilot-instructions.md or .github/instructions/*.instructions.md)"
1931
- );
1932
- }
1933
- return { rules, errors };
2442
+ ],
2443
+ errorMessage: "No Copilot configuration files found (.github/copilot-instructions.md or .github/instructions/*.instructions.md)"
2444
+ });
1934
2445
  }
1935
2446
 
1936
2447
  // src/parsers/cursor.ts
1937
- var import_node_path16 = require("path");
1938
- var import_gray_matter3 = __toESM(require("gray-matter"), 1);
2448
+ var import_node_path17 = require("path");
2449
+ var import_gray_matter4 = __toESM(require("gray-matter"), 1);
1939
2450
  var import_js_yaml = require("js-yaml");
1940
2451
  var import_mini6 = require("zod/mini");
1941
2452
  var customMatterOptions = {
@@ -2059,11 +2570,11 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2059
2570
  const rules = [];
2060
2571
  let ignorePatterns;
2061
2572
  let mcpServers;
2062
- const cursorFilePath = (0, import_node_path16.join)(baseDir, ".cursorrules");
2573
+ const cursorFilePath = (0, import_node_path17.join)(baseDir, ".cursorrules");
2063
2574
  if (await fileExists(cursorFilePath)) {
2064
2575
  try {
2065
2576
  const rawContent = await readFileContent(cursorFilePath);
2066
- const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
2577
+ const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
2067
2578
  const content = parsed.content.trim();
2068
2579
  if (content) {
2069
2580
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, "cursorrules");
@@ -2080,20 +2591,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2080
2591
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
2081
2592
  }
2082
2593
  }
2083
- const cursorRulesDir = (0, import_node_path16.join)(baseDir, ".cursor", "rules");
2594
+ const cursorRulesDir = (0, import_node_path17.join)(baseDir, ".cursor", "rules");
2084
2595
  if (await fileExists(cursorRulesDir)) {
2085
2596
  try {
2086
2597
  const { readdir: readdir2 } = await import("fs/promises");
2087
2598
  const files = await readdir2(cursorRulesDir);
2088
2599
  for (const file of files) {
2089
2600
  if (file.endsWith(".mdc")) {
2090
- const filePath = (0, import_node_path16.join)(cursorRulesDir, file);
2601
+ const filePath = (0, import_node_path17.join)(cursorRulesDir, file);
2091
2602
  try {
2092
2603
  const rawContent = await readFileContent(filePath);
2093
- const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
2604
+ const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
2094
2605
  const content = parsed.content.trim();
2095
2606
  if (content) {
2096
- const filename = (0, import_node_path16.basename)(file, ".mdc");
2607
+ const filename = (0, import_node_path17.basename)(file, ".mdc");
2097
2608
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
2098
2609
  rules.push({
2099
2610
  frontmatter,
@@ -2116,7 +2627,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2116
2627
  if (rules.length === 0) {
2117
2628
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
2118
2629
  }
2119
- const cursorIgnorePath = (0, import_node_path16.join)(baseDir, ".cursorignore");
2630
+ const cursorIgnorePath = (0, import_node_path17.join)(baseDir, ".cursorignore");
2120
2631
  if (await fileExists(cursorIgnorePath)) {
2121
2632
  try {
2122
2633
  const content = await readFileContent(cursorIgnorePath);
@@ -2129,7 +2640,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2129
2640
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
2130
2641
  }
2131
2642
  }
2132
- const cursorMcpPath = (0, import_node_path16.join)(baseDir, ".cursor", "mcp.json");
2643
+ const cursorMcpPath = (0, import_node_path17.join)(baseDir, ".cursor", "mcp.json");
2133
2644
  if (await fileExists(cursorMcpPath)) {
2134
2645
  try {
2135
2646
  const content = await readFileContent(cursorMcpPath);
@@ -2152,134 +2663,6 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2152
2663
  }
2153
2664
 
2154
2665
  // src/parsers/geminicli.ts
2155
- var import_node_path17 = require("path");
2156
- async function parseGeminiConfiguration(baseDir = process.cwd()) {
2157
- const errors = [];
2158
- const rules = [];
2159
- let ignorePatterns;
2160
- let mcpServers;
2161
- const geminiFilePath = (0, import_node_path17.join)(baseDir, "GEMINI.md");
2162
- if (!await fileExists(geminiFilePath)) {
2163
- errors.push("GEMINI.md file not found");
2164
- return { rules, errors };
2165
- }
2166
- try {
2167
- const geminiContent = await readFileContent(geminiFilePath);
2168
- const mainRule = parseGeminiMainFile(geminiContent, geminiFilePath);
2169
- if (mainRule) {
2170
- rules.push(mainRule);
2171
- }
2172
- const memoryDir = (0, import_node_path17.join)(baseDir, ".gemini", "memories");
2173
- if (await fileExists(memoryDir)) {
2174
- const memoryRules = await parseGeminiMemoryFiles(memoryDir);
2175
- rules.push(...memoryRules);
2176
- }
2177
- const settingsPath = (0, import_node_path17.join)(baseDir, ".gemini", "settings.json");
2178
- if (await fileExists(settingsPath)) {
2179
- const settingsResult = await parseGeminiSettings(settingsPath);
2180
- if (settingsResult.ignorePatterns) {
2181
- ignorePatterns = settingsResult.ignorePatterns;
2182
- }
2183
- if (settingsResult.mcpServers) {
2184
- mcpServers = settingsResult.mcpServers;
2185
- }
2186
- errors.push(...settingsResult.errors);
2187
- }
2188
- const aiexcludePath = (0, import_node_path17.join)(baseDir, ".aiexclude");
2189
- if (await fileExists(aiexcludePath)) {
2190
- const aiexcludePatterns = await parseAiexclude(aiexcludePath);
2191
- if (aiexcludePatterns.length > 0) {
2192
- ignorePatterns = ignorePatterns ? [...ignorePatterns, ...aiexcludePatterns] : aiexcludePatterns;
2193
- }
2194
- }
2195
- } catch (error) {
2196
- const errorMessage = error instanceof Error ? error.message : String(error);
2197
- errors.push(`Failed to parse Gemini configuration: ${errorMessage}`);
2198
- }
2199
- return {
2200
- rules,
2201
- errors,
2202
- ...ignorePatterns && { ignorePatterns },
2203
- ...mcpServers && { mcpServers }
2204
- };
2205
- }
2206
- function parseGeminiMainFile(content, filepath) {
2207
- const lines = content.split("\n");
2208
- let contentStartIndex = 0;
2209
- if (lines.some((line) => line.includes("| Document | Description | File Patterns |"))) {
2210
- const tableEndIndex = lines.findIndex(
2211
- (line, index) => index > 0 && line.trim() === "" && lines[index - 1]?.includes("|") && !lines[index + 1]?.includes("|")
2212
- );
2213
- if (tableEndIndex !== -1) {
2214
- contentStartIndex = tableEndIndex + 1;
2215
- }
2216
- }
2217
- const mainContent = lines.slice(contentStartIndex).join("\n").trim();
2218
- if (!mainContent) {
2219
- return null;
2220
- }
2221
- const frontmatter = {
2222
- root: false,
2223
- targets: ["geminicli"],
2224
- description: "Main Gemini CLI configuration",
2225
- globs: ["**/*"]
2226
- };
2227
- return {
2228
- frontmatter,
2229
- content: mainContent,
2230
- filename: "gemini-main",
2231
- filepath
2232
- };
2233
- }
2234
- async function parseGeminiMemoryFiles(memoryDir) {
2235
- const rules = [];
2236
- try {
2237
- const { readdir: readdir2 } = await import("fs/promises");
2238
- const files = await readdir2(memoryDir);
2239
- for (const file of files) {
2240
- if (file.endsWith(".md")) {
2241
- const filePath = (0, import_node_path17.join)(memoryDir, file);
2242
- const content = await readFileContent(filePath);
2243
- if (content.trim()) {
2244
- const filename = (0, import_node_path17.basename)(file, ".md");
2245
- const frontmatter = {
2246
- root: false,
2247
- targets: ["geminicli"],
2248
- description: `Memory file: ${filename}`,
2249
- globs: ["**/*"]
2250
- };
2251
- rules.push({
2252
- frontmatter,
2253
- content: content.trim(),
2254
- filename: `gemini-memory-${filename}`,
2255
- filepath: filePath
2256
- });
2257
- }
2258
- }
2259
- }
2260
- } catch {
2261
- }
2262
- return rules;
2263
- }
2264
- async function parseGeminiSettings(settingsPath) {
2265
- const errors = [];
2266
- let mcpServers;
2267
- try {
2268
- const content = await readFileContent(settingsPath);
2269
- const settings = JSON.parse(content);
2270
- const parseResult = RulesyncMcpConfigSchema.safeParse(settings);
2271
- if (parseResult.success && Object.keys(parseResult.data.mcpServers).length > 0) {
2272
- mcpServers = parseResult.data.mcpServers;
2273
- }
2274
- } catch (error) {
2275
- const errorMessage = error instanceof Error ? error.message : String(error);
2276
- errors.push(`Failed to parse settings.json: ${errorMessage}`);
2277
- }
2278
- return {
2279
- errors,
2280
- ...mcpServers && { mcpServers }
2281
- };
2282
- }
2283
2666
  async function parseAiexclude(aiexcludePath) {
2284
2667
  try {
2285
2668
  const content = await readFileContent(aiexcludePath);
@@ -2289,75 +2672,40 @@ async function parseAiexclude(aiexcludePath) {
2289
2672
  return [];
2290
2673
  }
2291
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
+ }
2292
2690
 
2293
2691
  // src/parsers/roo.ts
2294
- var import_node_path18 = require("path");
2295
2692
  async function parseRooConfiguration(baseDir = process.cwd()) {
2296
- const errors = [];
2297
- const rules = [];
2298
- const rooFilePath = (0, import_node_path18.join)(baseDir, ".roo", "instructions.md");
2299
- if (await fileExists(rooFilePath)) {
2300
- try {
2301
- const content = await readFileContent(rooFilePath);
2302
- if (content.trim()) {
2303
- const frontmatter = {
2304
- root: false,
2305
- targets: ["roo"],
2306
- description: "Roo Code instructions",
2307
- globs: ["**/*"]
2308
- };
2309
- rules.push({
2310
- frontmatter,
2311
- content: content.trim(),
2312
- filename: "roo-instructions",
2313
- filepath: rooFilePath
2314
- });
2315
- }
2316
- } catch (error) {
2317
- const errorMessage = error instanceof Error ? error.message : String(error);
2318
- errors.push(`Failed to parse .roo/instructions.md: ${errorMessage}`);
2319
- }
2320
- }
2321
- const rooRulesDir = (0, import_node_path18.join)(baseDir, ".roo", "rules");
2322
- if (await fileExists(rooRulesDir)) {
2323
- try {
2324
- const { readdir: readdir2 } = await import("fs/promises");
2325
- const files = await readdir2(rooRulesDir);
2326
- for (const file of files) {
2327
- if (file.endsWith(".md")) {
2328
- const filePath = (0, import_node_path18.join)(rooRulesDir, file);
2329
- try {
2330
- const content = await readFileContent(filePath);
2331
- if (content.trim()) {
2332
- const filename = file.replace(".md", "");
2333
- const frontmatter = {
2334
- root: false,
2335
- targets: ["roo"],
2336
- description: `Roo rule: ${filename}`,
2337
- globs: ["**/*"]
2338
- };
2339
- rules.push({
2340
- frontmatter,
2341
- content: content.trim(),
2342
- filename: `roo-${filename}`,
2343
- filepath: filePath
2344
- });
2345
- }
2346
- } catch (error) {
2347
- const errorMessage = error instanceof Error ? error.message : String(error);
2348
- errors.push(`Failed to parse ${filePath}: ${errorMessage}`);
2349
- }
2350
- }
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"
2351
2705
  }
2352
- } catch (error) {
2353
- const errorMessage = error instanceof Error ? error.message : String(error);
2354
- errors.push(`Failed to parse .roo/rules files: ${errorMessage}`);
2355
- }
2356
- }
2357
- if (rules.length === 0) {
2358
- errors.push("No Roo Code configuration files found (.roo/instructions.md or .roo/rules/*.md)");
2359
- }
2360
- return { rules, errors };
2706
+ ],
2707
+ errorMessage: "No Roo Code configuration files found (.roo/instructions.md or .roo/rules/*.md)"
2708
+ });
2361
2709
  }
2362
2710
 
2363
2711
  // src/core/importer.ts
@@ -2372,6 +2720,18 @@ async function importConfiguration(options) {
2372
2720
  }
2373
2721
  try {
2374
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
+ }
2375
2735
  case "claudecode": {
2376
2736
  const claudeResult = await parseClaudeConfiguration(baseDir);
2377
2737
  rules = claudeResult.rules;
@@ -2426,7 +2786,7 @@ async function importConfiguration(options) {
2426
2786
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
2427
2787
  return { success: false, rulesCreated: 0, errors };
2428
2788
  }
2429
- const rulesDirPath = (0, import_node_path19.join)(baseDir, rulesDir);
2789
+ const rulesDirPath = (0, import_node_path18.join)(baseDir, rulesDir);
2430
2790
  try {
2431
2791
  const { mkdir: mkdir3 } = await import("fs/promises");
2432
2792
  await mkdir3(rulesDirPath, { recursive: true });
@@ -2440,7 +2800,7 @@ async function importConfiguration(options) {
2440
2800
  try {
2441
2801
  const baseFilename = `${tool}__${rule.filename}`;
2442
2802
  const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
2443
- const filePath = (0, import_node_path19.join)(rulesDirPath, `${filename}.md`);
2803
+ const filePath = (0, import_node_path18.join)(rulesDirPath, `${filename}.md`);
2444
2804
  const content = generateRuleFileContent(rule);
2445
2805
  await writeFileContent(filePath, content);
2446
2806
  rulesCreated++;
@@ -2455,7 +2815,7 @@ async function importConfiguration(options) {
2455
2815
  let ignoreFileCreated = false;
2456
2816
  if (ignorePatterns && ignorePatterns.length > 0) {
2457
2817
  try {
2458
- const rulesyncignorePath = (0, import_node_path19.join)(baseDir, ".rulesyncignore");
2818
+ const rulesyncignorePath = (0, import_node_path18.join)(baseDir, ".rulesyncignore");
2459
2819
  const ignoreContent = `${ignorePatterns.join("\n")}
2460
2820
  `;
2461
2821
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -2471,7 +2831,7 @@ async function importConfiguration(options) {
2471
2831
  let mcpFileCreated = false;
2472
2832
  if (mcpServers && Object.keys(mcpServers).length > 0) {
2473
2833
  try {
2474
- const mcpPath = (0, import_node_path19.join)(baseDir, rulesDir, ".mcp.json");
2834
+ const mcpPath = (0, import_node_path18.join)(baseDir, rulesDir, ".mcp.json");
2475
2835
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
2476
2836
  `;
2477
2837
  await writeFileContent(mcpPath, mcpContent);
@@ -2493,13 +2853,13 @@ async function importConfiguration(options) {
2493
2853
  };
2494
2854
  }
2495
2855
  function generateRuleFileContent(rule) {
2496
- const frontmatter = import_gray_matter4.default.stringify("", rule.frontmatter);
2856
+ const frontmatter = import_gray_matter5.default.stringify("", rule.frontmatter);
2497
2857
  return frontmatter + rule.content;
2498
2858
  }
2499
2859
  async function generateUniqueFilename(rulesDir, baseFilename) {
2500
2860
  let filename = baseFilename;
2501
2861
  let counter = 1;
2502
- while (await fileExists((0, import_node_path19.join)(rulesDir, `${filename}.md`))) {
2862
+ while (await fileExists((0, import_node_path18.join)(rulesDir, `${filename}.md`))) {
2503
2863
  filename = `${baseFilename}-${counter}`;
2504
2864
  counter++;
2505
2865
  }
@@ -2509,6 +2869,8 @@ async function generateUniqueFilename(rulesDir, baseFilename) {
2509
2869
  // src/cli/commands/import.ts
2510
2870
  async function importCommand(options = {}) {
2511
2871
  const tools = [];
2872
+ if (options.augmentcode) tools.push("augmentcode");
2873
+ if (options.augmentcodeLegacy) tools.push("augmentcode-legacy");
2512
2874
  if (options.claudecode) tools.push("claudecode");
2513
2875
  if (options.cursor) tools.push("cursor");
2514
2876
  if (options.copilot) tools.push("copilot");
@@ -2517,7 +2879,7 @@ async function importCommand(options = {}) {
2517
2879
  if (options.geminicli) tools.push("geminicli");
2518
2880
  if (tools.length === 0) {
2519
2881
  console.error(
2520
- "\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)"
2521
2883
  );
2522
2884
  process.exit(1);
2523
2885
  }
@@ -2564,7 +2926,7 @@ async function importCommand(options = {}) {
2564
2926
  }
2565
2927
 
2566
2928
  // src/cli/commands/init.ts
2567
- var import_node_path20 = require("path");
2929
+ var import_node_path19 = require("path");
2568
2930
  async function initCommand() {
2569
2931
  const aiRulesDir = ".rulesync";
2570
2932
  console.log("Initializing rulesync...");
@@ -2611,7 +2973,7 @@ globs: ["**/*"]
2611
2973
  - Follow single responsibility principle
2612
2974
  `
2613
2975
  };
2614
- const filepath = (0, import_node_path20.join)(aiRulesDir, sampleFile.filename);
2976
+ const filepath = (0, import_node_path19.join)(aiRulesDir, sampleFile.filename);
2615
2977
  if (!await fileExists(filepath)) {
2616
2978
  await writeFileContent(filepath, sampleFile.content);
2617
2979
  console.log(`Created ${filepath}`);
@@ -2755,16 +3117,18 @@ async function watchCommand() {
2755
3117
 
2756
3118
  // src/cli/index.ts
2757
3119
  var program = new import_commander.Command();
2758
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.48.0");
3120
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.49.0");
2759
3121
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
2760
3122
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
2761
3123
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
2762
- 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);
2763
- 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(
2764
3126
  "-b, --base-dir <paths>",
2765
3127
  "Base directories to generate files (comma-separated for multiple paths)"
2766
3128
  ).option("-v, --verbose", "Verbose output").action(async (options) => {
2767
3129
  const tools = [];
3130
+ if (options.augmentcode) tools.push("augmentcode");
3131
+ if (options.augmentcodeLegacy) tools.push("augmentcode-legacy");
2768
3132
  if (options.copilot) tools.push("copilot");
2769
3133
  if (options.cursor) tools.push("cursor");
2770
3134
  if (options.cline) tools.push("cline");