rulesync 0.64.0 → 0.65.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.
Files changed (33) hide show
  1. package/README.md +7 -1
  2. package/dist/{amazonqcli-WVGYACHI.js → amazonqcli-MW7XTVPN.js} +2 -2
  3. package/dist/{augmentcode-DTHPPXWO.js → augmentcode-WCZCL7VR.js} +2 -2
  4. package/dist/{chunk-KKWJVA56.js → chunk-4NWMCTN5.js} +1 -1
  5. package/dist/{chunk-DMTCLQ4T.js → chunk-6AXPFPKI.js} +1 -1
  6. package/dist/{chunk-EID75W45.js → chunk-6SLEITCQ.js} +1 -1
  7. package/dist/{chunk-YPJW7Z5M.js → chunk-DM2B7XUB.js} +1 -1
  8. package/dist/{chunk-JX55DU6Y.js → chunk-FL5BF6JM.js} +1 -1
  9. package/dist/{chunk-TBXG53FV.js → chunk-GIAQWZQ4.js} +1 -1
  10. package/dist/{chunk-E2J3UBBK.js → chunk-I4NVS7GE.js} +1 -1
  11. package/dist/{chunk-6LSN7HSJ.js → chunk-JXOLLTNV.js} +14 -1
  12. package/dist/{chunk-HHJIL3YZ.js → chunk-LTWEI4PW.js} +1 -1
  13. package/dist/{chunk-LYVES5YR.js → chunk-M2AUM37M.js} +1 -0
  14. package/dist/{chunk-4NAQ5HL4.js → chunk-N6DASHJL.js} +1 -1
  15. package/dist/chunk-TX2CE4RR.js +17 -0
  16. package/dist/{chunk-TQOL7OKY.js → chunk-UGY5ALND.js} +1 -1
  17. package/dist/{chunk-LURFNGH4.js → chunk-VRWNZTGW.js} +1 -1
  18. package/dist/{chunk-FVPZQEWP.js → chunk-YC2BC7Z2.js} +1 -1
  19. package/dist/{claudecode-SSYLLUXX.js → claudecode-RZSJPPBU.js} +3 -3
  20. package/dist/{cline-5EUGKNZ6.js → cline-JTWWBQQ4.js} +3 -3
  21. package/dist/{codexcli-IGM2ADYK.js → codexcli-ATMFGRJR.js} +3 -3
  22. package/dist/{copilot-HSQO7ZCJ.js → copilot-H3CLGKDP.js} +2 -2
  23. package/dist/{cursor-ZB3XNGBK.js → cursor-ZUN5RZU6.js} +3 -3
  24. package/dist/{geminicli-FNRKH5GX.js → geminicli-Q5HPIQCU.js} +3 -3
  25. package/dist/index.cjs +297 -111
  26. package/dist/index.js +286 -133
  27. package/dist/{junie-3YGOSOGF.js → junie-JCLVC3MI.js} +3 -3
  28. package/dist/{kiro-B6WZNLY4.js → kiro-CNF6433S.js} +2 -2
  29. package/dist/{opencode-SZETJ62M.js → opencode-EBS3CED2.js} +2 -2
  30. package/dist/qwencode-JIT6KW7E.js +10 -0
  31. package/dist/{roo-KLTWVAKE.js → roo-KBTRH4TZ.js} +3 -3
  32. package/dist/{windsurf-IZEKUAID.js → windsurf-ZAAWL6JJ.js} +3 -3
  33. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -50,6 +50,7 @@ var init_tool_targets = __esm({
50
50
  "claudecode",
51
51
  "codexcli",
52
52
  "opencode",
53
+ "qwencode",
53
54
  "roo",
54
55
  "geminicli",
55
56
  "kiro",
@@ -796,6 +797,19 @@ var init_shared_factory = __esm({
796
797
  $schema: SCHEMA_URLS.OPENCODE,
797
798
  mcp: servers
798
799
  })
800
+ },
801
+ qwencode: {
802
+ target: "qwencode",
803
+ configPaths: [".qwen/settings.json"],
804
+ serverTransform: (server) => {
805
+ const { targets: _, ...serverConfig } = server;
806
+ const qwenServer = { ...serverConfig };
807
+ if (server.env) {
808
+ qwenServer.env = server.env;
809
+ }
810
+ return qwenServer;
811
+ },
812
+ configWrapper: configWrappers.mcpServers
799
813
  }
800
814
  };
801
815
  cursorMcpGenerator = createMcpGenerator("cursor");
@@ -1212,6 +1226,25 @@ var init_kiro = __esm({
1212
1226
  }
1213
1227
  });
1214
1228
 
1229
+ // src/generators/mcp/qwencode.ts
1230
+ var qwencode_exports = {};
1231
+ __export(qwencode_exports, {
1232
+ generateQwenCodeMcp: () => generateQwenCodeMcp,
1233
+ generateQwenCodeMcpConfiguration: () => generateQwenCodeMcpConfiguration
1234
+ });
1235
+ function generateQwenCodeMcp(config) {
1236
+ return generateMcpFromRegistry("qwencode", config);
1237
+ }
1238
+ function generateQwenCodeMcpConfiguration(mcpServers, baseDir = "") {
1239
+ return generateMcpConfigurationFilesFromRegistry("qwencode", mcpServers, baseDir);
1240
+ }
1241
+ var init_qwencode = __esm({
1242
+ "src/generators/mcp/qwencode.ts"() {
1243
+ "use strict";
1244
+ init_shared_factory();
1245
+ }
1246
+ });
1247
+
1215
1248
  // src/generators/mcp/roo.ts
1216
1249
  var roo_exports = {};
1217
1250
  __export(roo_exports, {
@@ -1272,14 +1305,6 @@ var init_opencode = __esm({
1272
1305
  // src/cli/index.ts
1273
1306
  var import_commander = require("commander");
1274
1307
 
1275
- // src/cli/commands/add.ts
1276
- var import_promises = require("fs/promises");
1277
- var path = __toESM(require("path"), 1);
1278
-
1279
- // src/utils/config-loader.ts
1280
- var import_c12 = require("c12");
1281
- var import_core = require("zod/v4/core");
1282
-
1283
1308
  // src/types/claudecode.ts
1284
1309
  var import_mini = require("zod/mini");
1285
1310
  var ClaudeSettingsSchema = import_mini.z.looseObject({
@@ -1332,6 +1357,7 @@ var OutputPathsSchema = import_mini5.z.object({
1332
1357
  claudecode: import_mini5.z.optional(import_mini5.z.string()),
1333
1358
  codexcli: import_mini5.z.optional(import_mini5.z.string()),
1334
1359
  opencode: import_mini5.z.optional(import_mini5.z.string()),
1360
+ qwencode: import_mini5.z.optional(import_mini5.z.string()),
1335
1361
  roo: import_mini5.z.optional(import_mini5.z.string()),
1336
1362
  geminicli: import_mini5.z.optional(import_mini5.z.string()),
1337
1363
  kiro: import_mini5.z.optional(import_mini5.z.string()),
@@ -1433,6 +1459,14 @@ var GenerateOptionsSchema = import_mini7.z.object({
1433
1459
  // src/types/index.ts
1434
1460
  init_tool_targets();
1435
1461
 
1462
+ // src/cli/commands/add.ts
1463
+ var import_promises = require("fs/promises");
1464
+ var path = __toESM(require("path"), 1);
1465
+
1466
+ // src/utils/config-loader.ts
1467
+ var import_c12 = require("c12");
1468
+ var import_core = require("zod/v4/core");
1469
+
1436
1470
  // src/utils/config.ts
1437
1471
  init_tool_targets();
1438
1472
  function getDefaultConfig() {
@@ -1448,6 +1482,7 @@ function getDefaultConfig() {
1448
1482
  claudecode: ".",
1449
1483
  codexcli: ".",
1450
1484
  opencode: ".",
1485
+ qwencode: ".qwen/memories",
1451
1486
  roo: ".roo/rules",
1452
1487
  geminicli: ".gemini/memories",
1453
1488
  kiro: ".kiro/steering",
@@ -1944,7 +1979,7 @@ export default config;
1944
1979
  }
1945
1980
 
1946
1981
  // src/cli/commands/generate.ts
1947
- var import_node_path13 = require("path");
1982
+ var import_node_path14 = require("path");
1948
1983
 
1949
1984
  // src/core/command-generator.ts
1950
1985
  var import_node_path5 = require("path");
@@ -2919,17 +2954,78 @@ async function generateKiroIgnoreFiles(rules, config, baseDir) {
2919
2954
  return generateIgnoreFile(rules, config, ignoreConfigs.kiro, baseDir);
2920
2955
  }
2921
2956
 
2957
+ // src/generators/ignore/qwencode.ts
2958
+ var import_node_path7 = require("path");
2959
+ function extractQwenCodeFileFilteringPatterns(content) {
2960
+ const filtering = {};
2961
+ const configBlocks = content.match(/```(?:json|javascript)\s*\n([\s\S]*?)\n```/g);
2962
+ if (configBlocks) {
2963
+ for (const block of configBlocks) {
2964
+ try {
2965
+ const jsonContent = block.replace(/```(?:json|javascript)\s*\n/, "").replace(/\n```$/, "");
2966
+ const parsed = JSON.parse(jsonContent);
2967
+ if (parsed.fileFiltering) {
2968
+ Object.assign(filtering, parsed.fileFiltering);
2969
+ }
2970
+ } catch {
2971
+ }
2972
+ }
2973
+ }
2974
+ if (content.includes("respectGitIgnore")) {
2975
+ if (content.includes("respectGitIgnore: false") || content.includes('"respectGitIgnore": false')) {
2976
+ filtering.respectGitIgnore = false;
2977
+ } else {
2978
+ filtering.respectGitIgnore = true;
2979
+ }
2980
+ }
2981
+ if (content.includes("enableRecursiveFileSearch")) {
2982
+ if (content.includes("enableRecursiveFileSearch: false") || content.includes('"enableRecursiveFileSearch": false')) {
2983
+ filtering.enableRecursiveFileSearch = false;
2984
+ } else {
2985
+ filtering.enableRecursiveFileSearch = true;
2986
+ }
2987
+ }
2988
+ return Object.keys(filtering).length > 0 ? filtering : void 0;
2989
+ }
2990
+ function generateQwenCodeConfiguration(rules) {
2991
+ const config = {};
2992
+ config.fileFiltering = {
2993
+ respectGitIgnore: true,
2994
+ enableRecursiveFileSearch: true
2995
+ };
2996
+ for (const rule of rules) {
2997
+ const ruleFiltering = extractQwenCodeFileFilteringPatterns(rule.content);
2998
+ if (ruleFiltering) {
2999
+ Object.assign(config.fileFiltering, ruleFiltering);
3000
+ }
3001
+ }
3002
+ return config;
3003
+ }
3004
+ async function generateQwenCodeIgnoreFiles(rules, config, baseDir) {
3005
+ const outputs = [];
3006
+ const outputPath = baseDir || process.cwd();
3007
+ const qwenConfig = generateQwenCodeConfiguration(rules);
3008
+ const settingsPath = (0, import_node_path7.join)(outputPath, ".qwen", "settings.json");
3009
+ outputs.push({
3010
+ tool: "qwencode",
3011
+ filepath: settingsPath,
3012
+ content: `${JSON.stringify(qwenConfig, null, 2)}
3013
+ `
3014
+ });
3015
+ return outputs;
3016
+ }
3017
+
2922
3018
  // src/generators/ignore/windsurf.ts
2923
3019
  function generateWindsurfIgnore(rules, config, baseDir) {
2924
3020
  return generateIgnoreFile(rules, config, ignoreConfigs.windsurf, baseDir);
2925
3021
  }
2926
3022
 
2927
3023
  // src/generators/rules/shared-helpers.ts
2928
- var import_node_path8 = require("path");
3024
+ var import_node_path9 = require("path");
2929
3025
  init_file();
2930
3026
 
2931
3027
  // src/utils/ignore.ts
2932
- var import_node_path7 = require("path");
3028
+ var import_node_path8 = require("path");
2933
3029
  var import_micromatch = __toESM(require("micromatch"), 1);
2934
3030
  init_file();
2935
3031
  init_logger();
@@ -2938,7 +3034,7 @@ async function loadIgnorePatterns(baseDir = process.cwd()) {
2938
3034
  if (cachedIgnorePatterns) {
2939
3035
  return cachedIgnorePatterns;
2940
3036
  }
2941
- const ignorePath = (0, import_node_path7.join)(baseDir, ".rulesyncignore");
3037
+ const ignorePath = (0, import_node_path8.join)(baseDir, ".rulesyncignore");
2942
3038
  if (!await fileExists(ignorePath)) {
2943
3039
  cachedIgnorePatterns = { patterns: [] };
2944
3040
  return cachedIgnorePatterns;
@@ -2992,7 +3088,7 @@ function addOutput(outputs, tool, config, baseDir, relativePath, content) {
2992
3088
  const outputDir = resolveOutputDir(config, tool, baseDir);
2993
3089
  outputs.push({
2994
3090
  tool,
2995
- filepath: (0, import_node_path8.join)(outputDir, relativePath),
3091
+ filepath: (0, import_node_path9.join)(outputDir, relativePath),
2996
3092
  content
2997
3093
  });
2998
3094
  }
@@ -3001,7 +3097,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
3001
3097
  for (const rule of rules) {
3002
3098
  const content = generatorConfig.generateContent(rule);
3003
3099
  const outputDir = resolveOutputDir(config, generatorConfig.tool, baseDir);
3004
- const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : (0, import_node_path8.join)(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
3100
+ const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : (0, import_node_path9.join)(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
3005
3101
  outputs.push({
3006
3102
  tool: generatorConfig.tool,
3007
3103
  filepath,
@@ -3029,7 +3125,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
3029
3125
  for (const rule of detailRules) {
3030
3126
  const content = generatorConfig.generateDetailContent(rule);
3031
3127
  const filepath = resolvePath(
3032
- (0, import_node_path8.join)(generatorConfig.detailSubDir, `${rule.filename}.md`),
3128
+ (0, import_node_path9.join)(generatorConfig.detailSubDir, `${rule.filename}.md`),
3033
3129
  baseDir
3034
3130
  );
3035
3131
  outputs.push({
@@ -3137,7 +3233,7 @@ function generateRuleFile(rule) {
3137
3233
  }
3138
3234
 
3139
3235
  // src/generators/rules/augmentcode.ts
3140
- var import_node_path9 = require("path");
3236
+ var import_node_path10 = require("path");
3141
3237
  async function generateAugmentcodeConfig(rules, config, baseDir) {
3142
3238
  const outputs = createOutputsArray();
3143
3239
  rules.forEach((rule) => {
@@ -3146,7 +3242,7 @@ async function generateAugmentcodeConfig(rules, config, baseDir) {
3146
3242
  "augmentcode",
3147
3243
  config,
3148
3244
  baseDir,
3149
- (0, import_node_path9.join)(".augment", "rules", `${rule.filename}.md`),
3245
+ (0, import_node_path10.join)(".augment", "rules", `${rule.filename}.md`),
3150
3246
  generateRuleFile2(rule)
3151
3247
  );
3152
3248
  });
@@ -3199,7 +3295,7 @@ function generateLegacyGuidelinesFile(allRules) {
3199
3295
  }
3200
3296
 
3201
3297
  // src/generators/rules/claudecode.ts
3202
- var import_node_path10 = require("path");
3298
+ var import_node_path11 = require("path");
3203
3299
  init_file();
3204
3300
  init_logger();
3205
3301
  async function generateClaudecodeConfig(rules, config, baseDir) {
@@ -3213,7 +3309,7 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
3213
3309
  generateDetailContent: generateMemoryFile,
3214
3310
  detailSubDir: ".claude/memories",
3215
3311
  updateAdditionalConfig: async (ignorePatterns, baseDir2) => {
3216
- const settingsPath = resolvePath((0, import_node_path10.join)(".claude", "settings.json"), baseDir2);
3312
+ const settingsPath = resolvePath((0, import_node_path11.join)(".claude", "settings.json"), baseDir2);
3217
3313
  await updateClaudeSettings(settingsPath, ignorePatterns);
3218
3314
  return [];
3219
3315
  }
@@ -3277,7 +3373,7 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
3277
3373
  }
3278
3374
 
3279
3375
  // src/generators/rules/generator-registry.ts
3280
- var import_node_path11 = require("path");
3376
+ var import_node_path12 = require("path");
3281
3377
  function determineCursorRuleType(frontmatter) {
3282
3378
  if (frontmatter.cursorRuleType) {
3283
3379
  return frontmatter.cursorRuleType;
@@ -3373,7 +3469,7 @@ var GENERATOR_REGISTRY = {
3373
3469
  },
3374
3470
  pathResolver: (rule, outputDir) => {
3375
3471
  const baseFilename = rule.filename.replace(/\.md$/, "");
3376
- return (0, import_node_path11.join)(outputDir, `${baseFilename}.instructions.md`);
3472
+ return (0, import_node_path12.join)(outputDir, `${baseFilename}.instructions.md`);
3377
3473
  }
3378
3474
  },
3379
3475
  cursor: {
@@ -3413,7 +3509,7 @@ var GENERATOR_REGISTRY = {
3413
3509
  return lines.join("\n");
3414
3510
  },
3415
3511
  pathResolver: (rule, outputDir) => {
3416
- return (0, import_node_path11.join)(outputDir, `${rule.filename}.mdc`);
3512
+ return (0, import_node_path12.join)(outputDir, `${rule.filename}.mdc`);
3417
3513
  }
3418
3514
  },
3419
3515
  codexcli: {
@@ -3449,10 +3545,10 @@ var GENERATOR_REGISTRY = {
3449
3545
  pathResolver: (rule, outputDir) => {
3450
3546
  const outputFormat = rule.frontmatter.windsurfOutputFormat || "directory";
3451
3547
  if (outputFormat === "single-file") {
3452
- return (0, import_node_path11.join)(outputDir, ".windsurf-rules");
3548
+ return (0, import_node_path12.join)(outputDir, ".windsurf-rules");
3453
3549
  } else {
3454
- const rulesDir = (0, import_node_path11.join)(outputDir, ".windsurf", "rules");
3455
- return (0, import_node_path11.join)(rulesDir, `${rule.filename}.md`);
3550
+ const rulesDir = (0, import_node_path12.join)(outputDir, ".windsurf", "rules");
3551
+ return (0, import_node_path12.join)(rulesDir, `${rule.filename}.md`);
3456
3552
  }
3457
3553
  }
3458
3554
  },
@@ -3515,6 +3611,22 @@ var GENERATOR_REGISTRY = {
3515
3611
  const lines = [];
3516
3612
  if (rule.frontmatter.description) {
3517
3613
  lines.push(`# ${rule.frontmatter.description}
3614
+ `);
3615
+ }
3616
+ lines.push(rule.content.trim());
3617
+ return lines.join("\n");
3618
+ }
3619
+ // Complex generation handled by existing generator
3620
+ },
3621
+ qwencode: {
3622
+ type: "complex",
3623
+ tool: "qwencode",
3624
+ fileExtension: ".md",
3625
+ // ignoreFileName omitted - Qwen Code uses git-aware filtering instead of dedicated ignore files
3626
+ generateContent: (rule) => {
3627
+ const lines = [];
3628
+ if (rule.frontmatter.description) {
3629
+ lines.push(`# ${rule.frontmatter.description}
3518
3630
  `);
3519
3631
  }
3520
3632
  lines.push(rule.content.trim());
@@ -3571,6 +3683,7 @@ var generateCopilotConfig = createSimpleGenerator("copilot");
3571
3683
  var generateWindsurfConfig = createSimpleGenerator("windsurf");
3572
3684
  var generateKiroConfig = createSimpleGenerator("kiro");
3573
3685
  var generateRooConfig = createSimpleGenerator("roo");
3686
+ var generateQwencodeConfig = createSimpleGenerator("qwencode");
3574
3687
 
3575
3688
  // src/generators/rules/codexcli.ts
3576
3689
  init_file();
@@ -3735,6 +3848,30 @@ function generateOpenCodeRootMarkdown(rootRule, memoryRules, _baseDir) {
3735
3848
  });
3736
3849
  }
3737
3850
 
3851
+ // src/generators/rules/qwencode.ts
3852
+ async function generateQwencodeConfig2(rules, config, baseDir) {
3853
+ const generatorConfig = {
3854
+ tool: "qwencode",
3855
+ fileExtension: ".md",
3856
+ // ignoreFileName omitted - Qwen Code uses git-aware filtering instead of dedicated ignore files
3857
+ generateContent: generateQwenMemoryMarkdown,
3858
+ generateDetailContent: generateQwenMemoryMarkdown,
3859
+ generateRootContent: generateQwenRootMarkdown,
3860
+ rootFilePath: "QWEN.md",
3861
+ detailSubDir: ".qwen/memories"
3862
+ };
3863
+ return generateComplexRules(rules, config, generatorConfig, baseDir);
3864
+ }
3865
+ function generateQwenMemoryMarkdown(rule) {
3866
+ return rule.content.trim();
3867
+ }
3868
+ function generateQwenRootMarkdown(rootRule, memoryRules, _baseDir) {
3869
+ return generateRootMarkdownWithXmlDocs(rootRule, memoryRules, {
3870
+ memorySubDir: ".qwen/memories",
3871
+ fallbackTitle: "Qwen Code Configuration"
3872
+ });
3873
+ }
3874
+
3738
3875
  // src/core/generator.ts
3739
3876
  init_logger();
3740
3877
  async function generateConfigurations(rules, config, targetTools, baseDir) {
@@ -3810,6 +3947,11 @@ async function generateForTool(tool, rules, config, baseDir) {
3810
3947
  }
3811
3948
  case "opencode":
3812
3949
  return generateOpenCodeConfig(rules, config, baseDir);
3950
+ case "qwencode": {
3951
+ const qwenRulesOutputs = await generateQwencodeConfig2(rules, config, baseDir);
3952
+ const qwenIgnoreOutputs = await generateQwenCodeIgnoreFiles(rules, config, baseDir);
3953
+ return [...qwenRulesOutputs, ...qwenIgnoreOutputs];
3954
+ }
3813
3955
  case "windsurf": {
3814
3956
  const windsurfRulesOutputs = await generateWindsurfConfig(rules, config, baseDir);
3815
3957
  const windsurfIgnoreOutputs = await generateWindsurfIgnore(rules, config, baseDir);
@@ -3822,7 +3964,7 @@ async function generateForTool(tool, rules, config, baseDir) {
3822
3964
  }
3823
3965
 
3824
3966
  // src/core/parser.ts
3825
- var import_node_path12 = require("path");
3967
+ var import_node_path13 = require("path");
3826
3968
  init_logger();
3827
3969
  async function parseRulesFromDirectory(aiRulesDir) {
3828
3970
  const ignorePatterns = await loadIgnorePatterns();
@@ -3876,7 +4018,7 @@ async function parseRuleFile(filepath) {
3876
4018
  },
3877
4019
  ...validatedData.tags !== void 0 && { tags: validatedData.tags }
3878
4020
  };
3879
- const filename = (0, import_node_path12.basename)(filepath, ".md");
4021
+ const filename = (0, import_node_path13.basename)(filepath, ".md");
3880
4022
  return {
3881
4023
  frontmatter,
3882
4024
  content: parsed.content,
@@ -3954,6 +4096,7 @@ init_cursor();
3954
4096
  init_geminicli();
3955
4097
  init_junie();
3956
4098
  init_kiro();
4099
+ init_qwencode();
3957
4100
  init_roo();
3958
4101
  init_windsurf();
3959
4102
 
@@ -4004,6 +4147,7 @@ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
4004
4147
  claudecode: ".",
4005
4148
  codexcli: ".",
4006
4149
  opencode: ".",
4150
+ qwencode: ".qwen/memories",
4007
4151
  roo: ".roo/rules",
4008
4152
  geminicli: ".gemini/memories",
4009
4153
  kiro: ".kiro/steering",
@@ -4047,6 +4191,10 @@ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
4047
4191
  ),
4048
4192
  kiro: async (servers, dir) => (await Promise.resolve().then(() => (init_kiro(), kiro_exports))).generateKiroMcpConfiguration(servers, dir),
4049
4193
  junie: async (servers, dir) => (await Promise.resolve().then(() => (init_junie(), junie_exports))).generateJunieMcpConfiguration(servers, dir),
4194
+ qwencode: async (servers, dir) => (await Promise.resolve().then(() => (init_qwencode(), qwencode_exports))).generateQwenCodeMcpConfiguration(
4195
+ servers,
4196
+ dir
4197
+ ),
4050
4198
  windsurf: async (servers, dir) => (await Promise.resolve().then(() => (init_windsurf(), windsurf_exports))).generateWindsurfMcpConfiguration(
4051
4199
  servers,
4052
4200
  dir
@@ -4077,35 +4225,40 @@ async function generateCommand(options = {}) {
4077
4225
  };
4078
4226
  const configResult = await loadConfig(configLoaderOptions);
4079
4227
  const cliOptions = {
4080
- ...options.tools !== void 0 && { tools: options.tools },
4228
+ tools: options.tools,
4081
4229
  ...options.verbose !== void 0 && { verbose: options.verbose },
4082
4230
  ...options.delete !== void 0 && { delete: options.delete },
4083
4231
  ...options.baseDirs !== void 0 && { baseDirs: options.baseDirs }
4084
4232
  };
4085
4233
  const config = mergeWithCliOptions(configResult.config, cliOptions);
4086
- logger.setVerbose(config.verbose || false);
4087
- if (options.tools && options.tools.length > 0) {
4088
- const configTargets = config.defaultTargets;
4089
- const cliTools = options.tools;
4090
- const cliToolsSet = new Set(cliTools);
4091
- const configTargetsSet = new Set(configTargets);
4092
- const notInConfig = cliTools.filter((tool) => !configTargetsSet.has(tool));
4093
- const notInCli = configTargets.filter((tool) => !cliToolsSet.has(tool));
4094
- if (notInConfig.length > 0 || notInCli.length > 0) {
4095
- logger.warn("\u26A0\uFE0F Warning: CLI tool selection differs from configuration!");
4096
- logger.warn(` Config targets: ${configTargets.join(", ")}`);
4097
- logger.warn(` CLI specified: ${cliTools.join(", ")}`);
4098
- if (notInConfig.length > 0) {
4099
- logger.warn(` Tools specified but not in config: ${notInConfig.join(", ")}`);
4100
- }
4101
- if (notInCli.length > 0) {
4102
- logger.warn(` Tools in config but not specified: ${notInCli.join(", ")}`);
4103
- }
4104
- logger.warn("\n The configuration file targets will be used.");
4105
- logger.warn(" To change targets, update your rulesync config file.");
4106
- logger.warn("");
4107
- }
4234
+ if (!config.defaultTargets || config.defaultTargets.length === 0) {
4235
+ const errorMessage = `\u274C Error: At least one tool must be specified.
4236
+
4237
+ Available tools:
4238
+ --augmentcode Generate for AugmentCode
4239
+ --augmentcode-legacy Generate for AugmentCode legacy format
4240
+ --copilot Generate for GitHub Copilot
4241
+ --cursor Generate for Cursor
4242
+ --cline Generate for Cline
4243
+ --codexcli Generate for OpenAI Codex CLI
4244
+ --claudecode Generate for Claude Code
4245
+ --roo Generate for Roo Code
4246
+ --geminicli Generate for Gemini CLI
4247
+ --junie Generate for JetBrains Junie
4248
+ --qwencode Generate for Qwen Code
4249
+ --kiro Generate for Kiro IDE
4250
+ --opencode Generate for OpenCode
4251
+ --windsurf Generate for Windsurf
4252
+
4253
+ Example:
4254
+ rulesync generate --copilot --cursor
4255
+
4256
+ Or specify tools in rulesync.jsonc:
4257
+ "tools": ["copilot", "cursor"]`;
4258
+ logger.error(errorMessage);
4259
+ process.exit(1);
4108
4260
  }
4261
+ logger.setVerbose(config.verbose || false);
4109
4262
  let baseDirs;
4110
4263
  if (config.baseDir) {
4111
4264
  baseDirs = Array.isArray(config.baseDir) ? config.baseDir : [config.baseDir];
@@ -4133,7 +4286,7 @@ async function generateCommand(options = {}) {
4133
4286
  logger.info("Deleting existing output directories...");
4134
4287
  const targetTools = config.defaultTargets;
4135
4288
  const deleteTasks = [];
4136
- const commandsDir = (0, import_node_path13.join)(config.aiRulesDir, "commands");
4289
+ const commandsDir = (0, import_node_path14.join)(config.aiRulesDir, "commands");
4137
4290
  const hasCommands = await fileExists(commandsDir);
4138
4291
  let hasCommandFiles = false;
4139
4292
  if (hasCommands) {
@@ -4148,12 +4301,12 @@ async function generateCommand(options = {}) {
4148
4301
  for (const tool of targetTools) {
4149
4302
  switch (tool) {
4150
4303
  case "augmentcode":
4151
- deleteTasks.push(removeDirectory((0, import_node_path13.join)(".augment", "rules")));
4152
- deleteTasks.push(removeDirectory((0, import_node_path13.join)(".augment", "ignore")));
4304
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".augment", "rules")));
4305
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".augment", "ignore")));
4153
4306
  break;
4154
4307
  case "augmentcode-legacy":
4155
4308
  deleteTasks.push(removeClaudeGeneratedFiles());
4156
- deleteTasks.push(removeDirectory((0, import_node_path13.join)(".augment", "ignore")));
4309
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".augment", "ignore")));
4157
4310
  break;
4158
4311
  case "copilot":
4159
4312
  deleteTasks.push(removeDirectory(config.outputPaths.copilot));
@@ -4167,19 +4320,19 @@ async function generateCommand(options = {}) {
4167
4320
  case "claudecode":
4168
4321
  deleteTasks.push(removeClaudeGeneratedFiles());
4169
4322
  if (hasCommandFiles) {
4170
- deleteTasks.push(removeDirectory((0, import_node_path13.join)(".claude", "commands")));
4323
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".claude", "commands")));
4171
4324
  }
4172
4325
  break;
4173
4326
  case "roo":
4174
4327
  deleteTasks.push(removeDirectory(config.outputPaths.roo));
4175
4328
  if (hasCommandFiles) {
4176
- deleteTasks.push(removeDirectory((0, import_node_path13.join)(".roo", "commands")));
4329
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".roo", "commands")));
4177
4330
  }
4178
4331
  break;
4179
4332
  case "geminicli":
4180
4333
  deleteTasks.push(removeDirectory(config.outputPaths.geminicli));
4181
4334
  if (hasCommandFiles) {
4182
- deleteTasks.push(removeDirectory((0, import_node_path13.join)(".gemini", "commands")));
4335
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".gemini", "commands")));
4183
4336
  }
4184
4337
  break;
4185
4338
  case "kiro":
@@ -4188,6 +4341,9 @@ async function generateCommand(options = {}) {
4188
4341
  case "opencode":
4189
4342
  deleteTasks.push(removeDirectory(config.outputPaths.opencode));
4190
4343
  break;
4344
+ case "qwencode":
4345
+ deleteTasks.push(removeDirectory(config.outputPaths.qwencode));
4346
+ break;
4191
4347
  case "windsurf":
4192
4348
  deleteTasks.push(removeDirectory(config.outputPaths.windsurf));
4193
4349
  break;
@@ -4281,10 +4437,10 @@ Generating configurations for base directory: ${baseDir}`);
4281
4437
 
4282
4438
  // src/cli/commands/gitignore.ts
4283
4439
  var import_node_fs2 = require("fs");
4284
- var import_node_path14 = require("path");
4440
+ var import_node_path15 = require("path");
4285
4441
  init_logger();
4286
4442
  var gitignoreCommand = async () => {
4287
- const gitignorePath = (0, import_node_path14.join)(process.cwd(), ".gitignore");
4443
+ const gitignorePath = (0, import_node_path15.join)(process.cwd(), ".gitignore");
4288
4444
  const rulesFilesToIgnore = [
4289
4445
  "# Generated by rulesync - AI tool configuration files",
4290
4446
  "**/.amazonq/rules/",
@@ -4306,6 +4462,8 @@ var gitignoreCommand = async () => {
4306
4462
  "**/GEMINI.md",
4307
4463
  "**/.gemini/memories/",
4308
4464
  "**/.gemini/commands/",
4465
+ "**/QWEN.md",
4466
+ "**/.qwen/memories/",
4309
4467
  "**/.aiexclude",
4310
4468
  "**/.aiignore",
4311
4469
  "**/.augmentignore",
@@ -4324,6 +4482,7 @@ var gitignoreCommand = async () => {
4324
4482
  "**/.vscode/mcp.json",
4325
4483
  "**/.codex/mcp-config.json",
4326
4484
  "**/.gemini/settings.json",
4485
+ "**/.qwen/settings.json",
4327
4486
  "**/.roo/mcp.json"
4328
4487
  ];
4329
4488
  let gitignoreContent = "";
@@ -4355,11 +4514,11 @@ ${linesToAdd.join("\n")}
4355
4514
  };
4356
4515
 
4357
4516
  // src/core/importer.ts
4358
- var import_node_path21 = require("path");
4517
+ var import_node_path22 = require("path");
4359
4518
  var import_gray_matter2 = __toESM(require("gray-matter"), 1);
4360
4519
 
4361
4520
  // src/parsers/shared-helpers.ts
4362
- var import_node_path15 = require("path");
4521
+ var import_node_path16 = require("path");
4363
4522
  init_file();
4364
4523
  async function parseConfigurationFiles(baseDir = process.cwd(), config) {
4365
4524
  const errors = [];
@@ -4417,7 +4576,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
4417
4576
  const files = await readdir2(dirPath);
4418
4577
  for (const file of files) {
4419
4578
  if (file.endsWith(dirConfig.filePattern)) {
4420
- const filePath = (0, import_node_path15.join)(dirPath, file);
4579
+ const filePath = (0, import_node_path16.join)(dirPath, file);
4421
4580
  const fileResult = await safeAsyncOperation(async () => {
4422
4581
  const rawContent = await readFileContent(filePath);
4423
4582
  let content;
@@ -4568,10 +4727,10 @@ async function parseMemoryFiles(memoryDir, config) {
4568
4727
  const files = await readdir2(memoryDir);
4569
4728
  for (const file of files) {
4570
4729
  if (file.endsWith(".md")) {
4571
- const filePath = (0, import_node_path15.join)(memoryDir, file);
4730
+ const filePath = (0, import_node_path16.join)(memoryDir, file);
4572
4731
  const content = await readFileContent(filePath);
4573
4732
  if (content.trim()) {
4574
- const filename = (0, import_node_path15.basename)(file, ".md");
4733
+ const filename = (0, import_node_path16.basename)(file, ".md");
4575
4734
  const frontmatter = {
4576
4735
  root: false,
4577
4736
  targets: [config.tool],
@@ -4598,10 +4757,10 @@ async function parseCommandsFiles(commandsDir, config) {
4598
4757
  const files = await readdir2(commandsDir);
4599
4758
  for (const file of files) {
4600
4759
  if (file.endsWith(".md")) {
4601
- const filePath = (0, import_node_path15.join)(commandsDir, file);
4760
+ const filePath = (0, import_node_path16.join)(commandsDir, file);
4602
4761
  const content = await readFileContent(filePath);
4603
4762
  if (content.trim()) {
4604
- const filename = (0, import_node_path15.basename)(file, ".md");
4763
+ const filename = (0, import_node_path16.basename)(file, ".md");
4605
4764
  let frontmatter;
4606
4765
  let ruleContent;
4607
4766
  try {
@@ -4690,7 +4849,7 @@ async function parseAmazonqcliConfiguration(baseDir = process.cwd()) {
4690
4849
  }
4691
4850
 
4692
4851
  // src/parsers/augmentcode.ts
4693
- var import_node_path16 = require("path");
4852
+ var import_node_path17 = require("path");
4694
4853
 
4695
4854
  // src/utils/parser-helpers.ts
4696
4855
  function createParseResult() {
@@ -4738,7 +4897,7 @@ async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
4738
4897
  async function parseUnifiedAugmentcode(baseDir, config) {
4739
4898
  const result = createParseResult();
4740
4899
  if (config.rulesDir) {
4741
- const rulesDir = (0, import_node_path16.join)(baseDir, config.rulesDir);
4900
+ const rulesDir = (0, import_node_path17.join)(baseDir, config.rulesDir);
4742
4901
  if (await fileExists(rulesDir)) {
4743
4902
  const rulesResult = await parseAugmentRules(rulesDir, config);
4744
4903
  addRules(result, rulesResult.rules);
@@ -4751,7 +4910,7 @@ async function parseUnifiedAugmentcode(baseDir, config) {
4751
4910
  }
4752
4911
  }
4753
4912
  if (config.legacyFilePath) {
4754
- const legacyPath = (0, import_node_path16.join)(baseDir, config.legacyFilePath);
4913
+ const legacyPath = (0, import_node_path17.join)(baseDir, config.legacyFilePath);
4755
4914
  if (await fileExists(legacyPath)) {
4756
4915
  const legacyResult = await parseAugmentGuidelines(legacyPath, config);
4757
4916
  if (legacyResult.rule) {
@@ -4775,7 +4934,7 @@ async function parseAugmentRules(rulesDir, config) {
4775
4934
  const files = await readdir2(rulesDir);
4776
4935
  for (const file of files) {
4777
4936
  if (file.endsWith(".md") || file.endsWith(".mdc")) {
4778
- const filePath = (0, import_node_path16.join)(rulesDir, file);
4937
+ const filePath = (0, import_node_path17.join)(rulesDir, file);
4779
4938
  try {
4780
4939
  const rawContent = await readFileContent(filePath);
4781
4940
  const parsed = parseFrontmatter(rawContent);
@@ -4783,7 +4942,7 @@ async function parseAugmentRules(rulesDir, config) {
4783
4942
  const description = extractStringField(parsed.data, "description", "");
4784
4943
  const tags = extractArrayField(parsed.data, "tags");
4785
4944
  const isRoot = ruleType === "always";
4786
- const filename = (0, import_node_path16.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
4945
+ const filename = (0, import_node_path17.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
4787
4946
  const frontmatter = {
4788
4947
  root: isRoot,
4789
4948
  targets: [config.targetName],
@@ -4875,7 +5034,7 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
4875
5034
  }
4876
5035
 
4877
5036
  // src/parsers/codexcli.ts
4878
- var import_node_path17 = require("path");
5037
+ var import_node_path18 = require("path");
4879
5038
 
4880
5039
  // src/parsers/copilot.ts
4881
5040
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
@@ -4898,7 +5057,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
4898
5057
  }
4899
5058
 
4900
5059
  // src/parsers/cursor.ts
4901
- var import_node_path18 = require("path");
5060
+ var import_node_path19 = require("path");
4902
5061
  var import_js_yaml = require("js-yaml");
4903
5062
  var import_mini8 = require("zod/mini");
4904
5063
  var customMatterOptions = {
@@ -5022,7 +5181,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
5022
5181
  const rules = [];
5023
5182
  let ignorePatterns;
5024
5183
  let mcpServers;
5025
- const cursorFilePath = (0, import_node_path18.join)(baseDir, ".cursorrules");
5184
+ const cursorFilePath = (0, import_node_path19.join)(baseDir, ".cursorrules");
5026
5185
  if (await fileExists(cursorFilePath)) {
5027
5186
  try {
5028
5187
  const rawContent = await readFileContent(cursorFilePath);
@@ -5043,20 +5202,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
5043
5202
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
5044
5203
  }
5045
5204
  }
5046
- const cursorRulesDir = (0, import_node_path18.join)(baseDir, ".cursor", "rules");
5205
+ const cursorRulesDir = (0, import_node_path19.join)(baseDir, ".cursor", "rules");
5047
5206
  if (await fileExists(cursorRulesDir)) {
5048
5207
  try {
5049
5208
  const { readdir: readdir2 } = await import("fs/promises");
5050
5209
  const files = await readdir2(cursorRulesDir);
5051
5210
  for (const file of files) {
5052
5211
  if (file.endsWith(".mdc")) {
5053
- const filePath = (0, import_node_path18.join)(cursorRulesDir, file);
5212
+ const filePath = (0, import_node_path19.join)(cursorRulesDir, file);
5054
5213
  try {
5055
5214
  const rawContent = await readFileContent(filePath);
5056
5215
  const parsed = parseFrontmatter(rawContent, { matterOptions: customMatterOptions });
5057
5216
  const content = parsed.content;
5058
5217
  if (content) {
5059
- const filename = (0, import_node_path18.basename)(file, ".mdc");
5218
+ const filename = (0, import_node_path19.basename)(file, ".mdc");
5060
5219
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
5061
5220
  rules.push({
5062
5221
  frontmatter,
@@ -5079,7 +5238,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
5079
5238
  if (rules.length === 0) {
5080
5239
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
5081
5240
  }
5082
- const cursorIgnorePath = (0, import_node_path18.join)(baseDir, ".cursorignore");
5241
+ const cursorIgnorePath = (0, import_node_path19.join)(baseDir, ".cursorignore");
5083
5242
  if (await fileExists(cursorIgnorePath)) {
5084
5243
  try {
5085
5244
  const content = await readFileContent(cursorIgnorePath);
@@ -5092,7 +5251,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
5092
5251
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
5093
5252
  }
5094
5253
  }
5095
- const cursorMcpPath = (0, import_node_path18.join)(baseDir, ".cursor", "mcp.json");
5254
+ const cursorMcpPath = (0, import_node_path19.join)(baseDir, ".cursor", "mcp.json");
5096
5255
  if (await fileExists(cursorMcpPath)) {
5097
5256
  try {
5098
5257
  const content = await readFileContent(cursorMcpPath);
@@ -5142,11 +5301,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
5142
5301
  }
5143
5302
 
5144
5303
  // src/parsers/junie.ts
5145
- var import_node_path19 = require("path");
5304
+ var import_node_path20 = require("path");
5146
5305
  async function parseJunieConfiguration(baseDir = process.cwd()) {
5147
5306
  const errors = [];
5148
5307
  const rules = [];
5149
- const guidelinesPath = (0, import_node_path19.join)(baseDir, ".junie", "guidelines.md");
5308
+ const guidelinesPath = (0, import_node_path20.join)(baseDir, ".junie", "guidelines.md");
5150
5309
  if (!await fileExists(guidelinesPath)) {
5151
5310
  errors.push(".junie/guidelines.md file not found");
5152
5311
  return { rules, errors };
@@ -5203,6 +5362,22 @@ async function parseOpenCodeConfiguration(baseDir = process.cwd()) {
5203
5362
  });
5204
5363
  }
5205
5364
 
5365
+ // src/parsers/qwencode.ts
5366
+ async function parseQwenConfiguration(baseDir = process.cwd()) {
5367
+ return parseMemoryBasedConfiguration(baseDir, {
5368
+ tool: "qwencode",
5369
+ mainFileName: "QWEN.md",
5370
+ memoryDirPath: ".qwen/memories",
5371
+ settingsPath: ".qwen/settings.json",
5372
+ mainDescription: "Main Qwen Code configuration",
5373
+ memoryDescription: "Memory file",
5374
+ filenamePrefix: "qwen",
5375
+ // Qwen Code uses git-aware filtering instead of dedicated ignore files
5376
+ // additionalIgnoreFile is omitted
5377
+ commandsDirPath: ".qwen/commands"
5378
+ });
5379
+ }
5380
+
5206
5381
  // src/parsers/roo.ts
5207
5382
  async function parseRooConfiguration(baseDir = process.cwd()) {
5208
5383
  return parseConfigurationFiles(baseDir, {
@@ -5225,7 +5400,7 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
5225
5400
 
5226
5401
  // src/parsers/windsurf.ts
5227
5402
  var import_promises3 = require("fs/promises");
5228
- var import_node_path20 = require("path");
5403
+ var import_node_path21 = require("path");
5229
5404
  init_logger();
5230
5405
 
5231
5406
  // src/core/importer.ts
@@ -5322,6 +5497,13 @@ async function importConfiguration(options) {
5322
5497
  mcpServers = opencodeResult.mcpServers;
5323
5498
  break;
5324
5499
  }
5500
+ case "qwencode": {
5501
+ const qwenResult = await parseQwenConfiguration(baseDir);
5502
+ rules = qwenResult.rules;
5503
+ errors.push(...qwenResult.errors);
5504
+ mcpServers = qwenResult.mcpServers;
5505
+ break;
5506
+ }
5325
5507
  default:
5326
5508
  errors.push(`Unsupported tool: ${tool}`);
5327
5509
  return { success: false, rulesCreated: 0, errors };
@@ -5334,7 +5516,7 @@ async function importConfiguration(options) {
5334
5516
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
5335
5517
  return { success: false, rulesCreated: 0, errors };
5336
5518
  }
5337
- const rulesDirPath = (0, import_node_path21.join)(baseDir, rulesDir);
5519
+ const rulesDirPath = (0, import_node_path22.join)(baseDir, rulesDir);
5338
5520
  try {
5339
5521
  const { mkdir: mkdir3 } = await import("fs/promises");
5340
5522
  await mkdir3(rulesDirPath, { recursive: true });
@@ -5349,17 +5531,17 @@ async function importConfiguration(options) {
5349
5531
  const baseFilename = rule.filename;
5350
5532
  let targetDir = rulesDirPath;
5351
5533
  if (rule.type === "command") {
5352
- targetDir = (0, import_node_path21.join)(rulesDirPath, "commands");
5534
+ targetDir = (0, import_node_path22.join)(rulesDirPath, "commands");
5353
5535
  const { mkdir: mkdir3 } = await import("fs/promises");
5354
5536
  await mkdir3(targetDir, { recursive: true });
5355
5537
  } else {
5356
5538
  if (!useLegacyLocation) {
5357
- targetDir = (0, import_node_path21.join)(rulesDirPath, "rules");
5539
+ targetDir = (0, import_node_path22.join)(rulesDirPath, "rules");
5358
5540
  const { mkdir: mkdir3 } = await import("fs/promises");
5359
5541
  await mkdir3(targetDir, { recursive: true });
5360
5542
  }
5361
5543
  }
5362
- const filePath = (0, import_node_path21.join)(targetDir, `${baseFilename}.md`);
5544
+ const filePath = (0, import_node_path22.join)(targetDir, `${baseFilename}.md`);
5363
5545
  const content = generateRuleFileContent(rule);
5364
5546
  await writeFileContent(filePath, content);
5365
5547
  rulesCreated++;
@@ -5374,7 +5556,7 @@ async function importConfiguration(options) {
5374
5556
  let ignoreFileCreated = false;
5375
5557
  if (ignorePatterns && ignorePatterns.length > 0) {
5376
5558
  try {
5377
- const rulesyncignorePath = (0, import_node_path21.join)(baseDir, ".rulesyncignore");
5559
+ const rulesyncignorePath = (0, import_node_path22.join)(baseDir, ".rulesyncignore");
5378
5560
  const ignoreContent = `${ignorePatterns.join("\n")}
5379
5561
  `;
5380
5562
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -5390,7 +5572,7 @@ async function importConfiguration(options) {
5390
5572
  let mcpFileCreated = false;
5391
5573
  if (mcpServers && Object.keys(mcpServers).length > 0) {
5392
5574
  try {
5393
- const mcpPath = (0, import_node_path21.join)(baseDir, rulesDir, ".mcp.json");
5575
+ const mcpPath = (0, import_node_path22.join)(baseDir, rulesDir, ".mcp.json");
5394
5576
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
5395
5577
  `;
5396
5578
  await writeFileContent(mcpPath, mcpContent);
@@ -5438,10 +5620,11 @@ async function importCommand(options = {}) {
5438
5620
  if (options.cline) tools.push("cline");
5439
5621
  if (options.roo) tools.push("roo");
5440
5622
  if (options.geminicli) tools.push("geminicli");
5623
+ if (options.qwencode) tools.push("qwencode");
5441
5624
  if (options.opencode) tools.push("opencode");
5442
5625
  if (tools.length === 0) {
5443
5626
  logger.error(
5444
- "\u274C Please specify one tool to import from (--amazonqcli, --augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli, --opencode)"
5627
+ "\u274C Please specify one tool to import from (--amazonqcli, --augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli, --qwencode, --opencode)"
5445
5628
  );
5446
5629
  process.exit(1);
5447
5630
  }
@@ -5489,7 +5672,7 @@ async function importCommand(options = {}) {
5489
5672
  }
5490
5673
 
5491
5674
  // src/cli/commands/init.ts
5492
- var import_node_path22 = require("path");
5675
+ var import_node_path23 = require("path");
5493
5676
  init_logger();
5494
5677
  async function initCommand(options = {}) {
5495
5678
  const configResult = await loadConfig();
@@ -5498,7 +5681,7 @@ async function initCommand(options = {}) {
5498
5681
  logger.log("Initializing rulesync...");
5499
5682
  await ensureDir(aiRulesDir);
5500
5683
  const useLegacy = options.legacy ?? config.legacy ?? false;
5501
- const rulesDir = useLegacy ? aiRulesDir : (0, import_node_path22.join)(aiRulesDir, "rules");
5684
+ const rulesDir = useLegacy ? aiRulesDir : (0, import_node_path23.join)(aiRulesDir, "rules");
5502
5685
  if (!useLegacy) {
5503
5686
  await ensureDir(rulesDir);
5504
5687
  }
@@ -5544,7 +5727,7 @@ globs: ["**/*"]
5544
5727
  - Follow single responsibility principle
5545
5728
  `
5546
5729
  };
5547
- const filepath = (0, import_node_path22.join)(rulesDir, sampleFile.filename);
5730
+ const filepath = (0, import_node_path23.join)(rulesDir, sampleFile.filename);
5548
5731
  if (!await fileExists(filepath)) {
5549
5732
  await writeFileContent(filepath, sampleFile.content);
5550
5733
  logger.success(`Created ${filepath}`);
@@ -5691,38 +5874,41 @@ async function watchCommand() {
5691
5874
 
5692
5875
  // src/cli/index.ts
5693
5876
  var program = new import_commander.Command();
5694
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.64.0");
5877
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.65.0");
5695
5878
  program.command("init").description("Initialize rulesync in current directory").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(initCommand);
5696
5879
  program.command("add <filename>").description("Add a new rule file").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(addCommand);
5697
5880
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
5698
- program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--augmentcode-legacy", "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("--junie", "Import from JetBrains Junie (.junie/guidelines.md)").option("--opencode", "Import from OpenCode (AGENTS.md)").option("-v, --verbose", "Verbose output").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(importCommand);
5699
- program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcode-legacy", "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("--codexcli", "Generate only for OpenAI Codex CLI").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--junie", "Generate only for JetBrains Junie").option("--kiro", "Generate only for Kiro IDE").option("--opencode", "Generate only for OpenCode").option("--windsurf", "Generate only for Windsurf").option("--delete", "Delete all existing files in output directories before generating").option(
5881
+ program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--augmentcode-legacy", "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("--junie", "Import from JetBrains Junie (.junie/guidelines.md)").option("--qwencode", "Import from Qwen Code (QWEN.md)").option("--opencode", "Import from OpenCode (AGENTS.md)").option("-v, --verbose", "Verbose output").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(importCommand);
5882
+ program.command("generate").description("Generate configuration files for AI tools").option("--all", "Generate for all supported AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--augmentcode-legacy", "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("--codexcli", "Generate only for OpenAI Codex CLI").option("--claudecode", "Generate only for Claude Code").option("--roo", "Generate only for Roo Code").option("--geminicli", "Generate only for Gemini CLI").option("--junie", "Generate only for JetBrains Junie").option("--qwencode", "Generate only for Qwen Code").option("--kiro", "Generate only for Kiro IDE").option("--opencode", "Generate only for OpenCode").option("--windsurf", "Generate only for Windsurf").option("--delete", "Delete all existing files in output directories before generating").option(
5700
5883
  "-b, --base-dir <paths>",
5701
5884
  "Base directories to generate files (comma-separated for multiple paths)"
5702
5885
  ).option("-v, --verbose", "Verbose output").option("-c, --config <path>", "Path to configuration file").option("--no-config", "Disable configuration file loading").action(async (options) => {
5703
5886
  const tools = [];
5704
- if (options.augmentcode) tools.push("augmentcode");
5705
- if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
5706
- if (options.copilot) tools.push("copilot");
5707
- if (options.cursor) tools.push("cursor");
5708
- if (options.cline) tools.push("cline");
5709
- if (options.codexcli) tools.push("codexcli");
5710
- if (options.claudecode) tools.push("claudecode");
5711
- if (options.roo) tools.push("roo");
5712
- if (options.geminicli) tools.push("geminicli");
5713
- if (options.junie) tools.push("junie");
5714
- if (options.kiro) tools.push("kiro");
5715
- if (options.opencode) tools.push("opencode");
5716
- if (options.windsurf) tools.push("windsurf");
5887
+ if (options.all) {
5888
+ tools.push(...ALL_TOOL_TARGETS);
5889
+ } else {
5890
+ if (options.augmentcode) tools.push("augmentcode");
5891
+ if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
5892
+ if (options.copilot) tools.push("copilot");
5893
+ if (options.cursor) tools.push("cursor");
5894
+ if (options.cline) tools.push("cline");
5895
+ if (options.codexcli) tools.push("codexcli");
5896
+ if (options.claudecode) tools.push("claudecode");
5897
+ if (options.roo) tools.push("roo");
5898
+ if (options.geminicli) tools.push("geminicli");
5899
+ if (options.junie) tools.push("junie");
5900
+ if (options.qwencode) tools.push("qwencode");
5901
+ if (options.kiro) tools.push("kiro");
5902
+ if (options.opencode) tools.push("opencode");
5903
+ if (options.windsurf) tools.push("windsurf");
5904
+ }
5717
5905
  const generateOptions = {
5718
5906
  verbose: options.verbose,
5907
+ tools: tools.length > 0 ? tools : void 0,
5719
5908
  delete: options.delete,
5720
5909
  config: options.config,
5721
5910
  noConfig: options.noConfig
5722
5911
  };
5723
- if (tools.length > 0) {
5724
- generateOptions.tools = tools;
5725
- }
5726
5912
  if (options.baseDir) {
5727
5913
  generateOptions.baseDirs = options.baseDir.split(",").map((dir) => dir.trim()).filter((dir) => dir.length > 0);
5728
5914
  }