rulesync 0.51.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10,10 +10,11 @@ import {
10
10
  } from "./chunk-OPZOVKIL.js";
11
11
  import {
12
12
  generateClaudeMcp
13
- } from "./chunk-4MZXYV5H.js";
13
+ } from "./chunk-FNL2KPM3.js";
14
14
  import {
15
15
  generateClineMcp
16
- } from "./chunk-AREA26HF.js";
16
+ } from "./chunk-HMMTSS5E.js";
17
+ import "./chunk-YPIFCGAP.js";
17
18
  import {
18
19
  generateCopilotMcp
19
20
  } from "./chunk-Y2XH4E5R.js";
@@ -728,9 +729,9 @@ export default config;
728
729
  }
729
730
 
730
731
  // src/cli/commands/generate.ts
731
- import { join as join15 } from "path";
732
+ import { join as join13 } from "path";
732
733
 
733
- // src/generators/ignore/augmentcode.ts
734
+ // src/generators/ignore/shared-factory.ts
734
735
  import { join as join3 } from "path";
735
736
 
736
737
  // src/generators/ignore/shared-helpers.ts
@@ -844,165 +845,43 @@ function extractAugmentCodeIgnorePatternsFromContent(content) {
844
845
  return patterns;
845
846
  }
846
847
 
847
- // src/generators/ignore/augmentcode.ts
848
- async function generateAugmentCodeIgnoreFiles(rules, config, baseDir) {
848
+ // src/generators/ignore/shared-factory.ts
849
+ function generateIgnoreFile(rules, config, ignoreConfig, baseDir) {
849
850
  const outputs = [];
850
- const augmentignoreContent = generateAugmentignoreContent(rules);
851
+ const content = generateIgnoreContent(rules, ignoreConfig);
851
852
  const outputPath = baseDir || process.cwd();
852
- const filepath = join3(outputPath, ".augmentignore");
853
+ const filepath = join3(outputPath, ignoreConfig.filename);
853
854
  outputs.push({
854
- tool: "augmentcode",
855
+ tool: ignoreConfig.tool,
855
856
  filepath,
856
- content: augmentignoreContent
857
+ content
857
858
  });
858
859
  return outputs;
859
860
  }
860
- function generateAugmentignoreContent(rules) {
861
- const lines = [
862
- "# Generated by rulesync - AugmentCode ignore patterns",
863
- "# AugmentCode uses a two-tier approach: .gitignore first, then .augmentignore",
864
- "# This file provides Augment-specific exclusions and re-inclusions",
865
- ""
866
- ];
867
- lines.push(
868
- "# Security and Secrets (critical exclusions)",
869
- "# Environment files",
870
- ".env*",
871
- "",
872
- "# Private keys and certificates",
873
- "*.pem",
874
- "*.key",
875
- "*.p12",
876
- "*.crt",
877
- "*.der",
878
- "",
879
- "# SSH keys",
880
- "id_rsa*",
881
- "id_dsa*",
882
- "",
883
- "# AWS credentials",
884
- ".aws/",
885
- "aws-exports.js",
886
- "",
887
- "# API keys and tokens",
888
- "**/apikeys/",
889
- "**/*_token*",
890
- "**/*_secret*",
891
- ""
892
- );
893
- lines.push(
894
- "# Build Artifacts and Dependencies",
895
- "# Build outputs",
896
- "dist/",
897
- "build/",
898
- "out/",
899
- "target/",
900
- "",
901
- "# Dependencies",
902
- "node_modules/",
903
- "venv/",
904
- "*.egg-info/",
905
- "",
906
- "# Logs",
907
- "*.log",
908
- "logs/",
909
- "",
910
- "# Temporary files",
911
- "*.tmp",
912
- "*.swp",
913
- "*.swo",
914
- "*~",
915
- ""
916
- );
917
- lines.push(
918
- "# Large Files and Media",
919
- "# Binary files",
920
- "*.jar",
921
- "*.png",
922
- "*.jpg",
923
- "*.jpeg",
924
- "*.gif",
925
- "*.mp4",
926
- "*.avi",
927
- "*.zip",
928
- "*.tar.gz",
929
- "*.rar",
930
- "",
931
- "# Database files",
932
- "*.sqlite",
933
- "*.db",
934
- "*.mdb",
935
- "",
936
- "# Data files",
937
- "*.csv",
938
- "*.tsv",
939
- "*.xlsx",
940
- ""
941
- );
942
- lines.push(
943
- "# Performance Optimization",
944
- "# Exclude files that are too large for effective AI processing",
945
- "**/*.{mp4,avi,mov,mkv}",
946
- "**/*.{zip,tar,gz,rar}",
947
- "**/*.{pdf,doc,docx}",
948
- "**/logs/**/*.log",
949
- "",
950
- "# But include small configuration files",
951
- "!**/config.{json,yaml,yml}",
952
- ""
953
- );
954
- const rulePatterns = extractIgnorePatternsFromRules(rules);
955
- const augmentPatterns = [];
956
- for (const rule of rules) {
957
- augmentPatterns.push(...extractAugmentCodeIgnorePatternsFromContent(rule.content));
861
+ function generateIgnoreContent(rules, config) {
862
+ const lines = [];
863
+ lines.push(...config.header);
864
+ lines.push("");
865
+ if (config.includeCommonPatterns) {
866
+ lines.push(...getCommonIgnorePatterns());
867
+ }
868
+ if (config.corePatterns.length > 0) {
869
+ lines.push(...config.corePatterns);
870
+ lines.push("");
958
871
  }
959
- const allPatterns = [...rulePatterns, ...augmentPatterns];
872
+ const rulePatterns = extractIgnorePatternsFromRules(rules);
873
+ const customPatterns = config.customPatternProcessor ? config.customPatternProcessor(rules) : [];
874
+ const allPatterns = [...rulePatterns, ...customPatterns];
960
875
  if (allPatterns.length > 0) {
961
- lines.push("# Project-specific patterns from rulesync rules");
876
+ const headerText = config.projectPatternsHeader || "# \u2500\u2500\u2500\u2500\u2500 Project-specific exclusions from rulesync rules \u2500\u2500\u2500\u2500\u2500";
877
+ lines.push(headerText);
962
878
  lines.push(...allPatterns);
963
879
  lines.push("");
964
880
  }
965
- lines.push(
966
- "# Team Collaboration",
967
- "# Exclude personal IDE settings",
968
- ".vscode/settings.json",
969
- ".idea/workspace.xml",
970
- "",
971
- "# But include shared team settings",
972
- "!.vscode/extensions.json",
973
- "!.idea/codeStyles/",
974
- "",
975
- "# Exclude test fixtures with sensitive data",
976
- "tests/fixtures/real-data/**",
977
- "",
978
- "# Re-include important documentation",
979
- "!vendor/*/README.md",
980
- "!third-party/*/LICENSE",
981
- ""
982
- );
983
881
  return lines.join("\n");
984
882
  }
985
-
986
- // src/generators/ignore/junie.ts
987
- import { join as join4 } from "path";
988
- async function generateJunieIgnoreFiles(rules, config, baseDir) {
989
- const outputs = [];
990
- const aiignoreContent = generateAiignoreContent(rules);
991
- const outputPath = baseDir || process.cwd();
992
- const filepath = join4(outputPath, ".aiignore");
993
- outputs.push({
994
- tool: "junie",
995
- filepath,
996
- content: aiignoreContent
997
- });
998
- return outputs;
999
- }
1000
- function generateAiignoreContent(rules) {
1001
- const lines = [
1002
- "# Generated by rulesync - JetBrains Junie AI ignore file",
1003
- "# This file controls which files the AI can access automatically",
1004
- "# AI must ask before reading or editing matched files/directories",
1005
- "",
883
+ function getCommonIgnorePatterns() {
884
+ return [
1006
885
  "# \u2500\u2500\u2500\u2500\u2500 Source Control Metadata \u2500\u2500\u2500\u2500\u2500",
1007
886
  ".git/",
1008
887
  ".svn/",
@@ -1114,93 +993,206 @@ function generateAiignoreContent(rules) {
1114
993
  "target/",
1115
994
  ""
1116
995
  ];
1117
- const rulePatterns = extractIgnorePatternsFromRules(rules);
1118
- if (rulePatterns.length > 0) {
1119
- lines.push("# \u2500\u2500\u2500\u2500\u2500 Project-specific exclusions from rulesync rules \u2500\u2500\u2500\u2500\u2500");
1120
- lines.push(...rulePatterns);
1121
- lines.push("");
996
+ }
997
+ var ignoreConfigs = {
998
+ junie: {
999
+ tool: "junie",
1000
+ filename: ".aiignore",
1001
+ header: [
1002
+ "# Generated by rulesync - JetBrains Junie AI ignore file",
1003
+ "# This file controls which files the AI can access automatically",
1004
+ "# AI must ask before reading or editing matched files/directories"
1005
+ ],
1006
+ corePatterns: [
1007
+ "# \u2500\u2500\u2500\u2500\u2500 Allow specific source files (uncomment as needed) \u2500\u2500\u2500\u2500\u2500",
1008
+ "# !src/**/*.ts",
1009
+ "# !src/**/*.js",
1010
+ "# !lib/**/*.py",
1011
+ "# !src/main/**/*.java"
1012
+ ],
1013
+ includeCommonPatterns: true
1014
+ },
1015
+ kiro: {
1016
+ tool: "kiro",
1017
+ filename: ".aiignore",
1018
+ header: [
1019
+ "# Generated by rulesync - Kiro AI-specific exclusions",
1020
+ "# This file excludes files that can be in Git but shouldn't be read by the AI"
1021
+ ],
1022
+ corePatterns: [
1023
+ "# Data files AI shouldn't process",
1024
+ "*.csv",
1025
+ "*.tsv",
1026
+ "*.sqlite",
1027
+ "*.db",
1028
+ "",
1029
+ "# Large binary files",
1030
+ "*.zip",
1031
+ "*.tar.gz",
1032
+ "*.rar",
1033
+ "",
1034
+ "# Sensitive documentation",
1035
+ "internal-docs/",
1036
+ "confidential/",
1037
+ "",
1038
+ "# Test data that might confuse AI",
1039
+ "test/fixtures/large-*.json",
1040
+ "benchmark-results/",
1041
+ "",
1042
+ "# Reinforce critical exclusions from .gitignore",
1043
+ "*.pem",
1044
+ "*.key",
1045
+ ".env*"
1046
+ ],
1047
+ includeCommonPatterns: false,
1048
+ projectPatternsHeader: "# Project-specific exclusions from rulesync rules"
1049
+ },
1050
+ augmentcode: {
1051
+ tool: "augmentcode",
1052
+ filename: ".augmentignore",
1053
+ header: [
1054
+ "# Generated by rulesync - AugmentCode ignore patterns",
1055
+ "# AugmentCode uses a two-tier approach: .gitignore first, then .augmentignore",
1056
+ "# This file provides Augment-specific exclusions and re-inclusions"
1057
+ ],
1058
+ corePatterns: [
1059
+ "# Security and Secrets (critical exclusions)",
1060
+ "# Environment files",
1061
+ ".env*",
1062
+ "",
1063
+ "# Private keys and certificates",
1064
+ "*.pem",
1065
+ "*.key",
1066
+ "*.p12",
1067
+ "*.crt",
1068
+ "*.der",
1069
+ "",
1070
+ "# SSH keys",
1071
+ "id_rsa*",
1072
+ "id_dsa*",
1073
+ "",
1074
+ "# AWS credentials",
1075
+ ".aws/",
1076
+ "aws-exports.js",
1077
+ "",
1078
+ "# API keys and tokens",
1079
+ "**/apikeys/",
1080
+ "**/*_token*",
1081
+ "**/*_secret*",
1082
+ "",
1083
+ "# Build Artifacts and Dependencies",
1084
+ "# Build outputs",
1085
+ "dist/",
1086
+ "build/",
1087
+ "out/",
1088
+ "target/",
1089
+ "",
1090
+ "# Dependencies",
1091
+ "node_modules/",
1092
+ "venv/",
1093
+ "*.egg-info/",
1094
+ "",
1095
+ "# Logs",
1096
+ "*.log",
1097
+ "logs/",
1098
+ "",
1099
+ "# Temporary files",
1100
+ "*.tmp",
1101
+ "*.swp",
1102
+ "*.swo",
1103
+ "*~",
1104
+ "",
1105
+ "# Large Files and Media",
1106
+ "# Binary files",
1107
+ "*.jar",
1108
+ "*.png",
1109
+ "*.jpg",
1110
+ "*.jpeg",
1111
+ "*.gif",
1112
+ "*.mp4",
1113
+ "*.avi",
1114
+ "*.zip",
1115
+ "*.tar.gz",
1116
+ "*.rar",
1117
+ "",
1118
+ "# Database files",
1119
+ "*.sqlite",
1120
+ "*.db",
1121
+ "*.mdb",
1122
+ "",
1123
+ "# Data files",
1124
+ "*.csv",
1125
+ "*.tsv",
1126
+ "*.xlsx",
1127
+ "",
1128
+ "# Performance Optimization",
1129
+ "# Exclude files that are too large for effective AI processing",
1130
+ "**/*.{mp4,avi,mov,mkv}",
1131
+ "**/*.{zip,tar,gz,rar}",
1132
+ "**/*.{pdf,doc,docx}",
1133
+ "**/logs/**/*.log",
1134
+ "",
1135
+ "# But include small configuration files",
1136
+ "!**/config.{json,yaml,yml}",
1137
+ "",
1138
+ "# Team Collaboration",
1139
+ "# Exclude personal IDE settings",
1140
+ ".vscode/settings.json",
1141
+ ".idea/workspace.xml",
1142
+ "",
1143
+ "# But include shared team settings",
1144
+ "!.vscode/extensions.json",
1145
+ "!.idea/codeStyles/",
1146
+ "",
1147
+ "# Exclude test fixtures with sensitive data",
1148
+ "tests/fixtures/real-data/**",
1149
+ "",
1150
+ "# Re-include important documentation",
1151
+ "!vendor/*/README.md",
1152
+ "!third-party/*/LICENSE"
1153
+ ],
1154
+ includeCommonPatterns: false,
1155
+ projectPatternsHeader: "# Project-specific patterns from rulesync rules",
1156
+ customPatternProcessor: (rules) => {
1157
+ const augmentPatterns = [];
1158
+ for (const rule of rules) {
1159
+ augmentPatterns.push(...extractAugmentCodeIgnorePatternsFromContent(rule.content));
1160
+ }
1161
+ return augmentPatterns;
1162
+ }
1122
1163
  }
1123
- lines.push(
1124
- "# \u2500\u2500\u2500\u2500\u2500 Allow specific source files (uncomment as needed) \u2500\u2500\u2500\u2500\u2500",
1125
- "# !src/**/*.ts",
1126
- "# !src/**/*.js",
1127
- "# !lib/**/*.py",
1128
- "# !src/main/**/*.java",
1129
- ""
1130
- );
1131
- return lines.join("\n");
1164
+ };
1165
+
1166
+ // src/generators/ignore/augmentcode.ts
1167
+ async function generateAugmentCodeIgnoreFiles(rules, config, baseDir) {
1168
+ return generateIgnoreFile(rules, config, ignoreConfigs.augmentcode, baseDir);
1169
+ }
1170
+
1171
+ // src/generators/ignore/junie.ts
1172
+ async function generateJunieIgnoreFiles(rules, config, baseDir) {
1173
+ return generateIgnoreFile(rules, config, ignoreConfigs.junie, baseDir);
1132
1174
  }
1133
1175
 
1134
1176
  // src/generators/ignore/kiro.ts
1135
- import { join as join5 } from "path";
1136
1177
  async function generateKiroIgnoreFiles(rules, config, baseDir) {
1137
- const outputs = [];
1138
- const aiignoreContent = generateAiignoreContent2(rules);
1139
- const outputPath = baseDir || process.cwd();
1140
- const filepath = join5(outputPath, ".aiignore");
1141
- outputs.push({
1142
- tool: "kiro",
1143
- filepath,
1144
- content: aiignoreContent
1145
- });
1146
- return outputs;
1147
- }
1148
- function generateAiignoreContent2(rules) {
1149
- const lines = [
1150
- "# Generated by rulesync - Kiro AI-specific exclusions",
1151
- "# This file excludes files that can be in Git but shouldn't be read by the AI",
1152
- ""
1153
- ];
1154
- lines.push(
1155
- "# Data files AI shouldn't process",
1156
- "*.csv",
1157
- "*.tsv",
1158
- "*.sqlite",
1159
- "*.db",
1160
- "",
1161
- "# Large binary files",
1162
- "*.zip",
1163
- "*.tar.gz",
1164
- "*.rar",
1165
- "",
1166
- "# Sensitive documentation",
1167
- "internal-docs/",
1168
- "confidential/",
1169
- "",
1170
- "# Test data that might confuse AI",
1171
- "test/fixtures/large-*.json",
1172
- "benchmark-results/",
1173
- "",
1174
- "# Reinforce critical exclusions from .gitignore",
1175
- "*.pem",
1176
- "*.key",
1177
- ".env*",
1178
- ""
1179
- );
1180
- const rulePatterns = extractIgnorePatternsFromRules(rules);
1181
- if (rulePatterns.length > 0) {
1182
- lines.push("# Project-specific exclusions from rulesync rules");
1183
- lines.push(...rulePatterns);
1184
- lines.push("");
1185
- }
1186
- return lines.join("\n");
1178
+ return generateIgnoreFile(rules, config, ignoreConfigs.kiro, baseDir);
1187
1179
  }
1188
1180
 
1189
1181
  // src/generators/rules/augmentcode.ts
1190
- import { join as join8 } from "path";
1182
+ import { join as join6 } from "path";
1191
1183
 
1192
1184
  // src/generators/rules/shared-helpers.ts
1193
- import { join as join7 } from "path";
1185
+ import { join as join5 } from "path";
1194
1186
 
1195
1187
  // src/utils/ignore.ts
1196
- import { join as join6 } from "path";
1188
+ import { join as join4 } from "path";
1197
1189
  import micromatch from "micromatch";
1198
1190
  var cachedIgnorePatterns = null;
1199
1191
  async function loadIgnorePatterns(baseDir = process.cwd()) {
1200
1192
  if (cachedIgnorePatterns) {
1201
1193
  return cachedIgnorePatterns;
1202
1194
  }
1203
- const ignorePath = join6(baseDir, ".rulesyncignore");
1195
+ const ignorePath = join4(baseDir, ".rulesyncignore");
1204
1196
  if (!await fileExists(ignorePath)) {
1205
1197
  cachedIgnorePatterns = { patterns: [] };
1206
1198
  return cachedIgnorePatterns;
@@ -1245,7 +1237,7 @@ function filterIgnoredFiles(files, ignorePatterns) {
1245
1237
 
1246
1238
  // src/generators/rules/shared-helpers.ts
1247
1239
  function resolveOutputDir(config, tool, baseDir) {
1248
- return baseDir ? join7(baseDir, config.outputPaths[tool]) : config.outputPaths[tool];
1240
+ return baseDir ? join5(baseDir, config.outputPaths[tool]) : config.outputPaths[tool];
1249
1241
  }
1250
1242
  function createOutputsArray() {
1251
1243
  return [];
@@ -1254,7 +1246,7 @@ function addOutput(outputs, tool, config, baseDir, relativePath, content) {
1254
1246
  const outputDir = resolveOutputDir(config, tool, baseDir);
1255
1247
  outputs.push({
1256
1248
  tool,
1257
- filepath: join7(outputDir, relativePath),
1249
+ filepath: join5(outputDir, relativePath),
1258
1250
  content
1259
1251
  });
1260
1252
  }
@@ -1263,7 +1255,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
1263
1255
  for (const rule of rules) {
1264
1256
  const content = generatorConfig.generateContent(rule);
1265
1257
  const outputDir = resolveOutputDir(config, generatorConfig.tool, baseDir);
1266
- const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : join7(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
1258
+ const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : join5(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
1267
1259
  outputs.push({
1268
1260
  tool: generatorConfig.tool,
1269
1261
  filepath,
@@ -1272,8 +1264,8 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
1272
1264
  }
1273
1265
  const ignorePatterns = await loadIgnorePatterns(baseDir);
1274
1266
  if (ignorePatterns.patterns.length > 0) {
1275
- const ignorePath = baseDir ? join7(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
1276
- const ignoreContent = generateIgnoreFile(ignorePatterns.patterns, generatorConfig.tool);
1267
+ const ignorePath = baseDir ? join5(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
1268
+ const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
1277
1269
  outputs.push({
1278
1270
  tool: generatorConfig.tool,
1279
1271
  filepath: ignorePath,
@@ -1290,7 +1282,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
1290
1282
  if (generatorConfig.generateDetailContent && generatorConfig.detailSubDir) {
1291
1283
  for (const rule of detailRules) {
1292
1284
  const content = generatorConfig.generateDetailContent(rule);
1293
- const filepath = baseDir ? join7(baseDir, generatorConfig.detailSubDir, `${rule.filename}.md`) : join7(generatorConfig.detailSubDir, `${rule.filename}.md`);
1285
+ const filepath = baseDir ? join5(baseDir, generatorConfig.detailSubDir, `${rule.filename}.md`) : join5(generatorConfig.detailSubDir, `${rule.filename}.md`);
1294
1286
  outputs.push({
1295
1287
  tool: generatorConfig.tool,
1296
1288
  filepath,
@@ -1300,7 +1292,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
1300
1292
  }
1301
1293
  if (generatorConfig.generateRootContent && generatorConfig.rootFilePath) {
1302
1294
  const rootContent = generatorConfig.generateRootContent(rootRule, detailRules, baseDir);
1303
- const rootFilepath = baseDir ? join7(baseDir, generatorConfig.rootFilePath) : generatorConfig.rootFilePath;
1295
+ const rootFilepath = baseDir ? join5(baseDir, generatorConfig.rootFilePath) : generatorConfig.rootFilePath;
1304
1296
  outputs.push({
1305
1297
  tool: generatorConfig.tool,
1306
1298
  filepath: rootFilepath,
@@ -1309,8 +1301,8 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
1309
1301
  }
1310
1302
  const ignorePatterns = await loadIgnorePatterns(baseDir);
1311
1303
  if (ignorePatterns.patterns.length > 0) {
1312
- const ignorePath = baseDir ? join7(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
1313
- const ignoreContent = generateIgnoreFile(ignorePatterns.patterns, generatorConfig.tool);
1304
+ const ignorePath = baseDir ? join5(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
1305
+ const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
1314
1306
  outputs.push({
1315
1307
  tool: generatorConfig.tool,
1316
1308
  filepath: ignorePath,
@@ -1326,7 +1318,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
1326
1318
  }
1327
1319
  return outputs;
1328
1320
  }
1329
- function generateIgnoreFile(patterns, tool) {
1321
+ function generateIgnoreFile2(patterns, tool) {
1330
1322
  const lines = [
1331
1323
  "# Generated by rulesync from .rulesyncignore",
1332
1324
  "# This file is automatically generated. Do not edit manually."
@@ -1359,7 +1351,7 @@ async function generateAugmentcodeConfig(rules, config, baseDir) {
1359
1351
  "augmentcode",
1360
1352
  config,
1361
1353
  baseDir,
1362
- join8(".augment", "rules", `${rule.filename}.md`),
1354
+ join6(".augment", "rules", `${rule.filename}.md`),
1363
1355
  generateRuleFile(rule)
1364
1356
  );
1365
1357
  });
@@ -1412,29 +1404,29 @@ function generateLegacyGuidelinesFile(allRules) {
1412
1404
  }
1413
1405
 
1414
1406
  // src/generators/rules/claudecode.ts
1415
- import { join as join9 } from "path";
1407
+ import { join as join7 } from "path";
1416
1408
  async function generateClaudecodeConfig(rules, config, baseDir) {
1417
1409
  const outputs = [];
1418
1410
  const rootRules = rules.filter((r) => r.frontmatter.root === true);
1419
1411
  const detailRules = rules.filter((r) => r.frontmatter.root === false);
1420
1412
  const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
1421
- const claudeOutputDir = baseDir ? join9(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
1413
+ const claudeOutputDir = baseDir ? join7(baseDir, config.outputPaths.claudecode) : config.outputPaths.claudecode;
1422
1414
  outputs.push({
1423
1415
  tool: "claudecode",
1424
- filepath: join9(claudeOutputDir, "CLAUDE.md"),
1416
+ filepath: join7(claudeOutputDir, "CLAUDE.md"),
1425
1417
  content: claudeMdContent
1426
1418
  });
1427
1419
  for (const rule of detailRules) {
1428
1420
  const memoryContent = generateMemoryFile(rule);
1429
1421
  outputs.push({
1430
1422
  tool: "claudecode",
1431
- filepath: join9(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
1423
+ filepath: join7(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
1432
1424
  content: memoryContent
1433
1425
  });
1434
1426
  }
1435
1427
  const ignorePatterns = await loadIgnorePatterns(baseDir);
1436
1428
  if (ignorePatterns.patterns.length > 0) {
1437
- const settingsPath = baseDir ? join9(baseDir, ".claude", "settings.json") : join9(".claude", "settings.json");
1429
+ const settingsPath = baseDir ? join7(baseDir, ".claude", "settings.json") : join7(".claude", "settings.json");
1438
1430
  await updateClaudeSettings(settingsPath, ignorePatterns.patterns);
1439
1431
  }
1440
1432
  return outputs;
@@ -1513,7 +1505,7 @@ async function generateClineConfig(rules, config, baseDir) {
1513
1505
  }
1514
1506
 
1515
1507
  // src/generators/rules/copilot.ts
1516
- import { join as join10 } from "path";
1508
+ import { join as join8 } from "path";
1517
1509
  async function generateCopilotConfig(rules, config, baseDir) {
1518
1510
  return generateComplexRulesConfig(
1519
1511
  rules,
@@ -1525,7 +1517,7 @@ async function generateCopilotConfig(rules, config, baseDir) {
1525
1517
  generateContent: generateCopilotMarkdown,
1526
1518
  getOutputPath: (rule, outputDir) => {
1527
1519
  const baseFilename = rule.filename.replace(/\.md$/, "");
1528
- return join10(outputDir, `${baseFilename}.instructions.md`);
1520
+ return join8(outputDir, `${baseFilename}.instructions.md`);
1529
1521
  }
1530
1522
  },
1531
1523
  baseDir
@@ -1546,7 +1538,7 @@ function generateCopilotMarkdown(rule) {
1546
1538
  }
1547
1539
 
1548
1540
  // src/generators/rules/cursor.ts
1549
- import { join as join11 } from "path";
1541
+ import { join as join9 } from "path";
1550
1542
  async function generateCursorConfig(rules, config, baseDir) {
1551
1543
  return generateComplexRulesConfig(
1552
1544
  rules,
@@ -1557,7 +1549,7 @@ async function generateCursorConfig(rules, config, baseDir) {
1557
1549
  ignoreFileName: ".cursorignore",
1558
1550
  generateContent: generateCursorMarkdown,
1559
1551
  getOutputPath: (rule, outputDir) => {
1560
- return join11(outputDir, `${rule.filename}.mdc`);
1552
+ return join9(outputDir, `${rule.filename}.mdc`);
1561
1553
  }
1562
1554
  },
1563
1555
  baseDir
@@ -1686,13 +1678,13 @@ function generateGuidelinesMarkdown(rootRule, detailRules) {
1686
1678
  }
1687
1679
 
1688
1680
  // src/generators/rules/kiro.ts
1689
- import { join as join12 } from "path";
1681
+ import { join as join10 } from "path";
1690
1682
  async function generateKiroConfig(rules, config, baseDir) {
1691
1683
  const outputs = [];
1692
1684
  for (const rule of rules) {
1693
1685
  const content = generateKiroMarkdown(rule);
1694
- const outputDir = baseDir ? join12(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
1695
- const filepath = join12(outputDir, `${rule.filename}.md`);
1686
+ const outputDir = baseDir ? join10(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
1687
+ const filepath = join10(outputDir, `${rule.filename}.md`);
1696
1688
  outputs.push({
1697
1689
  tool: "kiro",
1698
1690
  filepath,
@@ -2115,12 +2107,12 @@ async function generateCommand(options = {}) {
2115
2107
  for (const tool of targetTools) {
2116
2108
  switch (tool) {
2117
2109
  case "augmentcode":
2118
- deleteTasks.push(removeDirectory(join15(".augment", "rules")));
2119
- deleteTasks.push(removeDirectory(join15(".augment", "ignore")));
2110
+ deleteTasks.push(removeDirectory(join13(".augment", "rules")));
2111
+ deleteTasks.push(removeDirectory(join13(".augment", "ignore")));
2120
2112
  break;
2121
2113
  case "augmentcode-legacy":
2122
2114
  deleteTasks.push(removeClaudeGeneratedFiles());
2123
- deleteTasks.push(removeDirectory(join15(".augment", "ignore")));
2115
+ deleteTasks.push(removeDirectory(join13(".augment", "ignore")));
2124
2116
  break;
2125
2117
  case "copilot":
2126
2118
  deleteTasks.push(removeDirectory(config.outputPaths.copilot));
@@ -2215,9 +2207,9 @@ Generating configurations for base directory: ${baseDir}`);
2215
2207
 
2216
2208
  // src/cli/commands/gitignore.ts
2217
2209
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
2218
- import { join as join16 } from "path";
2210
+ import { join as join14 } from "path";
2219
2211
  var gitignoreCommand = async () => {
2220
- const gitignorePath = join16(process.cwd(), ".gitignore");
2212
+ const gitignorePath = join14(process.cwd(), ".gitignore");
2221
2213
  const rulesFilesToIgnore = [
2222
2214
  "# Generated by rulesync - AI tool configuration files",
2223
2215
  "**/.github/copilot-instructions.md",
@@ -2278,11 +2270,11 @@ ${linesToAdd.join("\n")}
2278
2270
  };
2279
2271
 
2280
2272
  // src/core/importer.ts
2281
- import { join as join22 } from "path";
2273
+ import { join as join20 } from "path";
2282
2274
  import matter5 from "gray-matter";
2283
2275
 
2284
2276
  // src/parsers/augmentcode.ts
2285
- import { basename as basename2, join as join17 } from "path";
2277
+ import { basename as basename2, join as join15 } from "path";
2286
2278
  import matter2 from "gray-matter";
2287
2279
 
2288
2280
  // src/utils/parser-helpers.ts
@@ -2323,7 +2315,7 @@ async function safeReadFile(operation, errorContext) {
2323
2315
  // src/parsers/augmentcode.ts
2324
2316
  async function parseAugmentcodeConfiguration(baseDir = process.cwd()) {
2325
2317
  const result = createParseResult();
2326
- const rulesDir = join17(baseDir, ".augment", "rules");
2318
+ const rulesDir = join15(baseDir, ".augment", "rules");
2327
2319
  if (await fileExists(rulesDir)) {
2328
2320
  const rulesResult = await parseAugmentRules(rulesDir);
2329
2321
  addRules(result, rulesResult.rules);
@@ -2341,7 +2333,7 @@ async function parseAugmentRules(rulesDir) {
2341
2333
  const files = await readdir2(rulesDir);
2342
2334
  for (const file of files) {
2343
2335
  if (file.endsWith(".md") || file.endsWith(".mdc")) {
2344
- const filePath = join17(rulesDir, file);
2336
+ const filePath = join15(rulesDir, file);
2345
2337
  try {
2346
2338
  const rawContent = await readFileContent(filePath);
2347
2339
  const parsed = matter2(rawContent);
@@ -2379,10 +2371,10 @@ async function parseAugmentRules(rulesDir) {
2379
2371
  }
2380
2372
 
2381
2373
  // src/parsers/augmentcode-legacy.ts
2382
- import { join as join18 } from "path";
2374
+ import { join as join16 } from "path";
2383
2375
  async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
2384
2376
  const result = createParseResult();
2385
- const guidelinesPath = join18(baseDir, ".augment-guidelines");
2377
+ const guidelinesPath = join16(baseDir, ".augment-guidelines");
2386
2378
  if (await fileExists(guidelinesPath)) {
2387
2379
  const guidelinesResult = await parseAugmentGuidelines(guidelinesPath);
2388
2380
  if (guidelinesResult.rule) {
@@ -2425,13 +2417,13 @@ async function parseAugmentGuidelines(guidelinesPath) {
2425
2417
  }
2426
2418
 
2427
2419
  // src/parsers/shared-helpers.ts
2428
- import { basename as basename3, join as join19 } from "path";
2420
+ import { basename as basename3, join as join17 } from "path";
2429
2421
  import matter3 from "gray-matter";
2430
2422
  async function parseConfigurationFiles(baseDir = process.cwd(), config) {
2431
2423
  const errors = [];
2432
2424
  const rules = [];
2433
2425
  if (config.mainFile) {
2434
- const mainFilePath = join19(baseDir, config.mainFile.path);
2426
+ const mainFilePath = join17(baseDir, config.mainFile.path);
2435
2427
  if (await fileExists(mainFilePath)) {
2436
2428
  try {
2437
2429
  const rawContent = await readFileContent(mainFilePath);
@@ -2459,7 +2451,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
2459
2451
  rules.push({
2460
2452
  frontmatter,
2461
2453
  content,
2462
- filename: `${config.tool}-instructions`,
2454
+ filename: "instructions",
2463
2455
  filepath: mainFilePath
2464
2456
  });
2465
2457
  }
@@ -2471,14 +2463,14 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
2471
2463
  }
2472
2464
  if (config.directories) {
2473
2465
  for (const dirConfig of config.directories) {
2474
- const dirPath = join19(baseDir, dirConfig.directory);
2466
+ const dirPath = join17(baseDir, dirConfig.directory);
2475
2467
  if (await fileExists(dirPath)) {
2476
2468
  try {
2477
2469
  const { readdir: readdir2 } = await import("fs/promises");
2478
2470
  const files = await readdir2(dirPath);
2479
2471
  for (const file of files) {
2480
2472
  if (file.endsWith(dirConfig.filePattern)) {
2481
- const filePath = join19(dirPath, file);
2473
+ const filePath = join17(dirPath, file);
2482
2474
  try {
2483
2475
  const rawContent = await readFileContent(filePath);
2484
2476
  let content;
@@ -2499,7 +2491,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
2499
2491
  rules.push({
2500
2492
  frontmatter,
2501
2493
  content,
2502
- filename: `${config.tool}-${filename}`,
2494
+ filename,
2503
2495
  filepath: filePath
2504
2496
  });
2505
2497
  }
@@ -2526,7 +2518,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
2526
2518
  const rules = [];
2527
2519
  let ignorePatterns;
2528
2520
  let mcpServers;
2529
- const mainFilePath = join19(baseDir, config.mainFileName);
2521
+ const mainFilePath = join17(baseDir, config.mainFileName);
2530
2522
  if (!await fileExists(mainFilePath)) {
2531
2523
  errors.push(`${config.mainFileName} file not found`);
2532
2524
  return { rules, errors };
@@ -2537,12 +2529,12 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
2537
2529
  if (mainRule) {
2538
2530
  rules.push(mainRule);
2539
2531
  }
2540
- const memoryDir = join19(baseDir, config.memoryDirPath);
2532
+ const memoryDir = join17(baseDir, config.memoryDirPath);
2541
2533
  if (await fileExists(memoryDir)) {
2542
2534
  const memoryRules = await parseMemoryFiles(memoryDir, config);
2543
2535
  rules.push(...memoryRules);
2544
2536
  }
2545
- const settingsPath = join19(baseDir, config.settingsPath);
2537
+ const settingsPath = join17(baseDir, config.settingsPath);
2546
2538
  if (await fileExists(settingsPath)) {
2547
2539
  const settingsResult = await parseSettingsFile(settingsPath, config.tool);
2548
2540
  if (settingsResult.ignorePatterns) {
@@ -2554,7 +2546,7 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
2554
2546
  errors.push(...settingsResult.errors);
2555
2547
  }
2556
2548
  if (config.additionalIgnoreFile) {
2557
- const additionalIgnorePath = join19(baseDir, config.additionalIgnoreFile.path);
2549
+ const additionalIgnorePath = join17(baseDir, config.additionalIgnoreFile.path);
2558
2550
  if (await fileExists(additionalIgnorePath)) {
2559
2551
  const additionalPatterns = await config.additionalIgnoreFile.parser(additionalIgnorePath);
2560
2552
  if (additionalPatterns.length > 0) {
@@ -2597,7 +2589,7 @@ function parseMainFile(content, filepath, config) {
2597
2589
  return {
2598
2590
  frontmatter,
2599
2591
  content: mainContent,
2600
- filename: `${config.filenamePrefix}-main`,
2592
+ filename: "main",
2601
2593
  filepath
2602
2594
  };
2603
2595
  }
@@ -2608,7 +2600,7 @@ async function parseMemoryFiles(memoryDir, config) {
2608
2600
  const files = await readdir2(memoryDir);
2609
2601
  for (const file of files) {
2610
2602
  if (file.endsWith(".md")) {
2611
- const filePath = join19(memoryDir, file);
2603
+ const filePath = join17(memoryDir, file);
2612
2604
  const content = await readFileContent(filePath);
2613
2605
  if (content.trim()) {
2614
2606
  const filename = basename3(file, ".md");
@@ -2621,7 +2613,7 @@ async function parseMemoryFiles(memoryDir, config) {
2621
2613
  rules.push({
2622
2614
  frontmatter,
2623
2615
  content: content.trim(),
2624
- filename: `${config.filenamePrefix}-memory-${filename}`,
2616
+ filename,
2625
2617
  filepath: filePath
2626
2618
  });
2627
2619
  }
@@ -2724,7 +2716,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
2724
2716
  }
2725
2717
 
2726
2718
  // src/parsers/cursor.ts
2727
- import { basename as basename4, join as join20 } from "path";
2719
+ import { basename as basename4, join as join18 } from "path";
2728
2720
  import matter4 from "gray-matter";
2729
2721
  import { DEFAULT_SCHEMA, FAILSAFE_SCHEMA, load } from "js-yaml";
2730
2722
  import { z as z6 } from "zod/mini";
@@ -2849,7 +2841,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2849
2841
  const rules = [];
2850
2842
  let ignorePatterns;
2851
2843
  let mcpServers;
2852
- const cursorFilePath = join20(baseDir, ".cursorrules");
2844
+ const cursorFilePath = join18(baseDir, ".cursorrules");
2853
2845
  if (await fileExists(cursorFilePath)) {
2854
2846
  try {
2855
2847
  const rawContent = await readFileContent(cursorFilePath);
@@ -2870,14 +2862,14 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2870
2862
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
2871
2863
  }
2872
2864
  }
2873
- const cursorRulesDir = join20(baseDir, ".cursor", "rules");
2865
+ const cursorRulesDir = join18(baseDir, ".cursor", "rules");
2874
2866
  if (await fileExists(cursorRulesDir)) {
2875
2867
  try {
2876
2868
  const { readdir: readdir2 } = await import("fs/promises");
2877
2869
  const files = await readdir2(cursorRulesDir);
2878
2870
  for (const file of files) {
2879
2871
  if (file.endsWith(".mdc")) {
2880
- const filePath = join20(cursorRulesDir, file);
2872
+ const filePath = join18(cursorRulesDir, file);
2881
2873
  try {
2882
2874
  const rawContent = await readFileContent(filePath);
2883
2875
  const parsed = matter4(rawContent, customMatterOptions);
@@ -2906,7 +2898,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2906
2898
  if (rules.length === 0) {
2907
2899
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
2908
2900
  }
2909
- const cursorIgnorePath = join20(baseDir, ".cursorignore");
2901
+ const cursorIgnorePath = join18(baseDir, ".cursorignore");
2910
2902
  if (await fileExists(cursorIgnorePath)) {
2911
2903
  try {
2912
2904
  const content = await readFileContent(cursorIgnorePath);
@@ -2919,7 +2911,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
2919
2911
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
2920
2912
  }
2921
2913
  }
2922
- const cursorMcpPath = join20(baseDir, ".cursor", "mcp.json");
2914
+ const cursorMcpPath = join18(baseDir, ".cursor", "mcp.json");
2923
2915
  if (await fileExists(cursorMcpPath)) {
2924
2916
  try {
2925
2917
  const content = await readFileContent(cursorMcpPath);
@@ -2968,11 +2960,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
2968
2960
  }
2969
2961
 
2970
2962
  // src/parsers/junie.ts
2971
- import { join as join21 } from "path";
2963
+ import { join as join19 } from "path";
2972
2964
  async function parseJunieConfiguration(baseDir = process.cwd()) {
2973
2965
  const errors = [];
2974
2966
  const rules = [];
2975
- const guidelinesPath = join21(baseDir, ".junie", "guidelines.md");
2967
+ const guidelinesPath = join19(baseDir, ".junie", "guidelines.md");
2976
2968
  if (!await fileExists(guidelinesPath)) {
2977
2969
  errors.push(".junie/guidelines.md file not found");
2978
2970
  return { rules, errors };
@@ -3107,7 +3099,7 @@ async function importConfiguration(options) {
3107
3099
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
3108
3100
  return { success: false, rulesCreated: 0, errors };
3109
3101
  }
3110
- const rulesDirPath = join22(baseDir, rulesDir);
3102
+ const rulesDirPath = join20(baseDir, rulesDir);
3111
3103
  try {
3112
3104
  const { mkdir: mkdir3 } = await import("fs/promises");
3113
3105
  await mkdir3(rulesDirPath, { recursive: true });
@@ -3119,9 +3111,9 @@ async function importConfiguration(options) {
3119
3111
  let rulesCreated = 0;
3120
3112
  for (const rule of rules) {
3121
3113
  try {
3122
- const baseFilename = `${tool}__${rule.filename}`;
3114
+ const baseFilename = rule.filename;
3123
3115
  const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
3124
- const filePath = join22(rulesDirPath, `${filename}.md`);
3116
+ const filePath = join20(rulesDirPath, `${filename}.md`);
3125
3117
  const content = generateRuleFileContent(rule);
3126
3118
  await writeFileContent(filePath, content);
3127
3119
  rulesCreated++;
@@ -3136,7 +3128,7 @@ async function importConfiguration(options) {
3136
3128
  let ignoreFileCreated = false;
3137
3129
  if (ignorePatterns && ignorePatterns.length > 0) {
3138
3130
  try {
3139
- const rulesyncignorePath = join22(baseDir, ".rulesyncignore");
3131
+ const rulesyncignorePath = join20(baseDir, ".rulesyncignore");
3140
3132
  const ignoreContent = `${ignorePatterns.join("\n")}
3141
3133
  `;
3142
3134
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -3152,7 +3144,7 @@ async function importConfiguration(options) {
3152
3144
  let mcpFileCreated = false;
3153
3145
  if (mcpServers && Object.keys(mcpServers).length > 0) {
3154
3146
  try {
3155
- const mcpPath = join22(baseDir, rulesDir, ".mcp.json");
3147
+ const mcpPath = join20(baseDir, rulesDir, ".mcp.json");
3156
3148
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
3157
3149
  `;
3158
3150
  await writeFileContent(mcpPath, mcpContent);
@@ -3180,7 +3172,7 @@ function generateRuleFileContent(rule) {
3180
3172
  async function generateUniqueFilename(rulesDir, baseFilename) {
3181
3173
  let filename = baseFilename;
3182
3174
  let counter = 1;
3183
- while (await fileExists(join22(rulesDir, `${filename}.md`))) {
3175
+ while (await fileExists(join20(rulesDir, `${filename}.md`))) {
3184
3176
  filename = `${baseFilename}-${counter}`;
3185
3177
  counter++;
3186
3178
  }
@@ -3247,7 +3239,7 @@ async function importCommand(options = {}) {
3247
3239
  }
3248
3240
 
3249
3241
  // src/cli/commands/init.ts
3250
- import { join as join23 } from "path";
3242
+ import { join as join21 } from "path";
3251
3243
  async function initCommand() {
3252
3244
  const aiRulesDir = ".rulesync";
3253
3245
  console.log("Initializing rulesync...");
@@ -3294,7 +3286,7 @@ globs: ["**/*"]
3294
3286
  - Follow single responsibility principle
3295
3287
  `
3296
3288
  };
3297
- const filepath = join23(aiRulesDir, sampleFile.filename);
3289
+ const filepath = join21(aiRulesDir, sampleFile.filename);
3298
3290
  if (!await fileExists(filepath)) {
3299
3291
  await writeFileContent(filepath, sampleFile.content);
3300
3292
  console.log(`Created ${filepath}`);
@@ -3438,7 +3430,7 @@ async function watchCommand() {
3438
3430
 
3439
3431
  // src/cli/index.ts
3440
3432
  var program = new Command();
3441
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.51.0");
3433
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.53.0");
3442
3434
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
3443
3435
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
3444
3436
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);