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.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-DMTCLQ4T.js";
3
- import "./chunk-4NAQ5HL4.js";
4
- import "./chunk-EID75W45.js";
5
- import "./chunk-LURFNGH4.js";
6
- import "./chunk-HHJIL3YZ.js";
2
+ import "./chunk-6AXPFPKI.js";
3
+ import "./chunk-N6DASHJL.js";
4
+ import "./chunk-6SLEITCQ.js";
5
+ import "./chunk-TX2CE4RR.js";
6
+ import "./chunk-VRWNZTGW.js";
7
+ import "./chunk-LTWEI4PW.js";
7
8
  import {
8
9
  ensureDir,
9
10
  fileExists,
@@ -15,33 +16,25 @@ import {
15
16
  removeDirectory,
16
17
  resolvePath,
17
18
  writeFileContent
18
- } from "./chunk-YPJW7Z5M.js";
19
- import "./chunk-E2J3UBBK.js";
20
- import "./chunk-FVPZQEWP.js";
21
- import "./chunk-JX55DU6Y.js";
22
- import "./chunk-TQOL7OKY.js";
23
- import "./chunk-KKWJVA56.js";
24
- import "./chunk-TBXG53FV.js";
25
- import "./chunk-6LSN7HSJ.js";
19
+ } from "./chunk-DM2B7XUB.js";
20
+ import "./chunk-I4NVS7GE.js";
21
+ import "./chunk-YC2BC7Z2.js";
22
+ import "./chunk-FL5BF6JM.js";
23
+ import "./chunk-UGY5ALND.js";
24
+ import "./chunk-4NWMCTN5.js";
25
+ import "./chunk-GIAQWZQ4.js";
26
+ import "./chunk-JXOLLTNV.js";
26
27
  import {
27
28
  ALL_TOOL_TARGETS,
28
29
  RulesyncTargetsSchema,
29
30
  ToolTargetSchema,
30
31
  ToolTargetsSchema,
31
32
  isToolTarget
32
- } from "./chunk-LYVES5YR.js";
33
+ } from "./chunk-M2AUM37M.js";
33
34
 
34
35
  // src/cli/index.ts
35
36
  import { Command } from "commander";
36
37
 
37
- // src/cli/commands/add.ts
38
- import { mkdir, writeFile } from "fs/promises";
39
- import * as path from "path";
40
-
41
- // src/utils/config-loader.ts
42
- import { loadConfig as loadC12Config } from "c12";
43
- import { $ZodError } from "zod/v4/core";
44
-
45
38
  // src/types/claudecode.ts
46
39
  import { z } from "zod/mini";
47
40
  var ClaudeSettingsSchema = z.looseObject({
@@ -91,6 +84,7 @@ var OutputPathsSchema = z4.object({
91
84
  claudecode: z4.optional(z4.string()),
92
85
  codexcli: z4.optional(z4.string()),
93
86
  opencode: z4.optional(z4.string()),
87
+ qwencode: z4.optional(z4.string()),
94
88
  roo: z4.optional(z4.string()),
95
89
  geminicli: z4.optional(z4.string()),
96
90
  kiro: z4.optional(z4.string()),
@@ -187,6 +181,14 @@ var GenerateOptionsSchema = z6.object({
187
181
  watch: z6.optional(z6.boolean())
188
182
  });
189
183
 
184
+ // src/cli/commands/add.ts
185
+ import { mkdir, writeFile } from "fs/promises";
186
+ import * as path from "path";
187
+
188
+ // src/utils/config-loader.ts
189
+ import { loadConfig as loadC12Config } from "c12";
190
+ import { $ZodError } from "zod/v4/core";
191
+
190
192
  // src/utils/config.ts
191
193
  function getDefaultConfig() {
192
194
  return {
@@ -201,6 +203,7 @@ function getDefaultConfig() {
201
203
  claudecode: ".",
202
204
  codexcli: ".",
203
205
  opencode: ".",
206
+ qwencode: ".qwen/memories",
204
207
  roo: ".roo/rules",
205
208
  geminicli: ".gemini/memories",
206
209
  kiro: ".kiro/steering",
@@ -691,7 +694,7 @@ export default config;
691
694
  }
692
695
 
693
696
  // src/cli/commands/generate.ts
694
- import { join as join12 } from "path";
697
+ import { join as join13 } from "path";
695
698
 
696
699
  // src/core/command-generator.ts
697
700
  import { join as join3 } from "path";
@@ -1661,23 +1664,84 @@ async function generateKiroIgnoreFiles(rules, config, baseDir) {
1661
1664
  return generateIgnoreFile(rules, config, ignoreConfigs.kiro, baseDir);
1662
1665
  }
1663
1666
 
1667
+ // src/generators/ignore/qwencode.ts
1668
+ import { join as join5 } from "path";
1669
+ function extractQwenCodeFileFilteringPatterns(content) {
1670
+ const filtering = {};
1671
+ const configBlocks = content.match(/```(?:json|javascript)\s*\n([\s\S]*?)\n```/g);
1672
+ if (configBlocks) {
1673
+ for (const block of configBlocks) {
1674
+ try {
1675
+ const jsonContent = block.replace(/```(?:json|javascript)\s*\n/, "").replace(/\n```$/, "");
1676
+ const parsed = JSON.parse(jsonContent);
1677
+ if (parsed.fileFiltering) {
1678
+ Object.assign(filtering, parsed.fileFiltering);
1679
+ }
1680
+ } catch {
1681
+ }
1682
+ }
1683
+ }
1684
+ if (content.includes("respectGitIgnore")) {
1685
+ if (content.includes("respectGitIgnore: false") || content.includes('"respectGitIgnore": false')) {
1686
+ filtering.respectGitIgnore = false;
1687
+ } else {
1688
+ filtering.respectGitIgnore = true;
1689
+ }
1690
+ }
1691
+ if (content.includes("enableRecursiveFileSearch")) {
1692
+ if (content.includes("enableRecursiveFileSearch: false") || content.includes('"enableRecursiveFileSearch": false')) {
1693
+ filtering.enableRecursiveFileSearch = false;
1694
+ } else {
1695
+ filtering.enableRecursiveFileSearch = true;
1696
+ }
1697
+ }
1698
+ return Object.keys(filtering).length > 0 ? filtering : void 0;
1699
+ }
1700
+ function generateQwenCodeConfiguration(rules) {
1701
+ const config = {};
1702
+ config.fileFiltering = {
1703
+ respectGitIgnore: true,
1704
+ enableRecursiveFileSearch: true
1705
+ };
1706
+ for (const rule of rules) {
1707
+ const ruleFiltering = extractQwenCodeFileFilteringPatterns(rule.content);
1708
+ if (ruleFiltering) {
1709
+ Object.assign(config.fileFiltering, ruleFiltering);
1710
+ }
1711
+ }
1712
+ return config;
1713
+ }
1714
+ async function generateQwenCodeIgnoreFiles(rules, config, baseDir) {
1715
+ const outputs = [];
1716
+ const outputPath = baseDir || process.cwd();
1717
+ const qwenConfig = generateQwenCodeConfiguration(rules);
1718
+ const settingsPath = join5(outputPath, ".qwen", "settings.json");
1719
+ outputs.push({
1720
+ tool: "qwencode",
1721
+ filepath: settingsPath,
1722
+ content: `${JSON.stringify(qwenConfig, null, 2)}
1723
+ `
1724
+ });
1725
+ return outputs;
1726
+ }
1727
+
1664
1728
  // src/generators/ignore/windsurf.ts
1665
1729
  function generateWindsurfIgnore(rules, config, baseDir) {
1666
1730
  return generateIgnoreFile(rules, config, ignoreConfigs.windsurf, baseDir);
1667
1731
  }
1668
1732
 
1669
1733
  // src/generators/rules/shared-helpers.ts
1670
- import { join as join6 } from "path";
1734
+ import { join as join7 } from "path";
1671
1735
 
1672
1736
  // src/utils/ignore.ts
1673
- import { join as join5 } from "path";
1737
+ import { join as join6 } from "path";
1674
1738
  import micromatch from "micromatch";
1675
1739
  var cachedIgnorePatterns = null;
1676
1740
  async function loadIgnorePatterns(baseDir = process.cwd()) {
1677
1741
  if (cachedIgnorePatterns) {
1678
1742
  return cachedIgnorePatterns;
1679
1743
  }
1680
- const ignorePath = join5(baseDir, ".rulesyncignore");
1744
+ const ignorePath = join6(baseDir, ".rulesyncignore");
1681
1745
  if (!await fileExists(ignorePath)) {
1682
1746
  cachedIgnorePatterns = { patterns: [] };
1683
1747
  return cachedIgnorePatterns;
@@ -1731,7 +1795,7 @@ function addOutput(outputs, tool, config, baseDir, relativePath, content) {
1731
1795
  const outputDir = resolveOutputDir(config, tool, baseDir);
1732
1796
  outputs.push({
1733
1797
  tool,
1734
- filepath: join6(outputDir, relativePath),
1798
+ filepath: join7(outputDir, relativePath),
1735
1799
  content
1736
1800
  });
1737
1801
  }
@@ -1740,7 +1804,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
1740
1804
  for (const rule of rules) {
1741
1805
  const content = generatorConfig.generateContent(rule);
1742
1806
  const outputDir = resolveOutputDir(config, generatorConfig.tool, baseDir);
1743
- const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : join6(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
1807
+ const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : join7(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
1744
1808
  outputs.push({
1745
1809
  tool: generatorConfig.tool,
1746
1810
  filepath,
@@ -1768,7 +1832,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
1768
1832
  for (const rule of detailRules) {
1769
1833
  const content = generatorConfig.generateDetailContent(rule);
1770
1834
  const filepath = resolvePath(
1771
- join6(generatorConfig.detailSubDir, `${rule.filename}.md`),
1835
+ join7(generatorConfig.detailSubDir, `${rule.filename}.md`),
1772
1836
  baseDir
1773
1837
  );
1774
1838
  outputs.push({
@@ -1876,7 +1940,7 @@ function generateRuleFile(rule) {
1876
1940
  }
1877
1941
 
1878
1942
  // src/generators/rules/augmentcode.ts
1879
- import { join as join7 } from "path";
1943
+ import { join as join8 } from "path";
1880
1944
  async function generateAugmentcodeConfig(rules, config, baseDir) {
1881
1945
  const outputs = createOutputsArray();
1882
1946
  rules.forEach((rule) => {
@@ -1885,7 +1949,7 @@ async function generateAugmentcodeConfig(rules, config, baseDir) {
1885
1949
  "augmentcode",
1886
1950
  config,
1887
1951
  baseDir,
1888
- join7(".augment", "rules", `${rule.filename}.md`),
1952
+ join8(".augment", "rules", `${rule.filename}.md`),
1889
1953
  generateRuleFile2(rule)
1890
1954
  );
1891
1955
  });
@@ -1938,7 +2002,7 @@ function generateLegacyGuidelinesFile(allRules) {
1938
2002
  }
1939
2003
 
1940
2004
  // src/generators/rules/claudecode.ts
1941
- import { join as join8 } from "path";
2005
+ import { join as join9 } from "path";
1942
2006
  async function generateClaudecodeConfig(rules, config, baseDir) {
1943
2007
  const generatorConfig = {
1944
2008
  tool: "claudecode",
@@ -1950,7 +2014,7 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
1950
2014
  generateDetailContent: generateMemoryFile,
1951
2015
  detailSubDir: ".claude/memories",
1952
2016
  updateAdditionalConfig: async (ignorePatterns, baseDir2) => {
1953
- const settingsPath = resolvePath(join8(".claude", "settings.json"), baseDir2);
2017
+ const settingsPath = resolvePath(join9(".claude", "settings.json"), baseDir2);
1954
2018
  await updateClaudeSettings(settingsPath, ignorePatterns);
1955
2019
  return [];
1956
2020
  }
@@ -2014,7 +2078,7 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
2014
2078
  }
2015
2079
 
2016
2080
  // src/generators/rules/generator-registry.ts
2017
- import { join as join9 } from "path";
2081
+ import { join as join10 } from "path";
2018
2082
  function determineCursorRuleType(frontmatter) {
2019
2083
  if (frontmatter.cursorRuleType) {
2020
2084
  return frontmatter.cursorRuleType;
@@ -2110,7 +2174,7 @@ var GENERATOR_REGISTRY = {
2110
2174
  },
2111
2175
  pathResolver: (rule, outputDir) => {
2112
2176
  const baseFilename = rule.filename.replace(/\.md$/, "");
2113
- return join9(outputDir, `${baseFilename}.instructions.md`);
2177
+ return join10(outputDir, `${baseFilename}.instructions.md`);
2114
2178
  }
2115
2179
  },
2116
2180
  cursor: {
@@ -2150,7 +2214,7 @@ var GENERATOR_REGISTRY = {
2150
2214
  return lines.join("\n");
2151
2215
  },
2152
2216
  pathResolver: (rule, outputDir) => {
2153
- return join9(outputDir, `${rule.filename}.mdc`);
2217
+ return join10(outputDir, `${rule.filename}.mdc`);
2154
2218
  }
2155
2219
  },
2156
2220
  codexcli: {
@@ -2186,10 +2250,10 @@ var GENERATOR_REGISTRY = {
2186
2250
  pathResolver: (rule, outputDir) => {
2187
2251
  const outputFormat = rule.frontmatter.windsurfOutputFormat || "directory";
2188
2252
  if (outputFormat === "single-file") {
2189
- return join9(outputDir, ".windsurf-rules");
2253
+ return join10(outputDir, ".windsurf-rules");
2190
2254
  } else {
2191
- const rulesDir = join9(outputDir, ".windsurf", "rules");
2192
- return join9(rulesDir, `${rule.filename}.md`);
2255
+ const rulesDir = join10(outputDir, ".windsurf", "rules");
2256
+ return join10(rulesDir, `${rule.filename}.md`);
2193
2257
  }
2194
2258
  }
2195
2259
  },
@@ -2252,6 +2316,22 @@ var GENERATOR_REGISTRY = {
2252
2316
  const lines = [];
2253
2317
  if (rule.frontmatter.description) {
2254
2318
  lines.push(`# ${rule.frontmatter.description}
2319
+ `);
2320
+ }
2321
+ lines.push(rule.content.trim());
2322
+ return lines.join("\n");
2323
+ }
2324
+ // Complex generation handled by existing generator
2325
+ },
2326
+ qwencode: {
2327
+ type: "complex",
2328
+ tool: "qwencode",
2329
+ fileExtension: ".md",
2330
+ // ignoreFileName omitted - Qwen Code uses git-aware filtering instead of dedicated ignore files
2331
+ generateContent: (rule) => {
2332
+ const lines = [];
2333
+ if (rule.frontmatter.description) {
2334
+ lines.push(`# ${rule.frontmatter.description}
2255
2335
  `);
2256
2336
  }
2257
2337
  lines.push(rule.content.trim());
@@ -2308,6 +2388,7 @@ var generateCopilotConfig = createSimpleGenerator("copilot");
2308
2388
  var generateWindsurfConfig = createSimpleGenerator("windsurf");
2309
2389
  var generateKiroConfig = createSimpleGenerator("kiro");
2310
2390
  var generateRooConfig = createSimpleGenerator("roo");
2391
+ var generateQwencodeConfig = createSimpleGenerator("qwencode");
2311
2392
 
2312
2393
  // src/utils/xml-document-generator.ts
2313
2394
  import { XMLBuilder } from "fast-xml-parser";
@@ -2469,6 +2550,30 @@ function generateOpenCodeRootMarkdown(rootRule, memoryRules, _baseDir) {
2469
2550
  });
2470
2551
  }
2471
2552
 
2553
+ // src/generators/rules/qwencode.ts
2554
+ async function generateQwencodeConfig2(rules, config, baseDir) {
2555
+ const generatorConfig = {
2556
+ tool: "qwencode",
2557
+ fileExtension: ".md",
2558
+ // ignoreFileName omitted - Qwen Code uses git-aware filtering instead of dedicated ignore files
2559
+ generateContent: generateQwenMemoryMarkdown,
2560
+ generateDetailContent: generateQwenMemoryMarkdown,
2561
+ generateRootContent: generateQwenRootMarkdown,
2562
+ rootFilePath: "QWEN.md",
2563
+ detailSubDir: ".qwen/memories"
2564
+ };
2565
+ return generateComplexRules(rules, config, generatorConfig, baseDir);
2566
+ }
2567
+ function generateQwenMemoryMarkdown(rule) {
2568
+ return rule.content.trim();
2569
+ }
2570
+ function generateQwenRootMarkdown(rootRule, memoryRules, _baseDir) {
2571
+ return generateRootMarkdownWithXmlDocs(rootRule, memoryRules, {
2572
+ memorySubDir: ".qwen/memories",
2573
+ fallbackTitle: "Qwen Code Configuration"
2574
+ });
2575
+ }
2576
+
2472
2577
  // src/core/generator.ts
2473
2578
  async function generateConfigurations(rules, config, targetTools, baseDir) {
2474
2579
  const outputs = createOutputsArray();
@@ -2543,6 +2648,11 @@ async function generateForTool(tool, rules, config, baseDir) {
2543
2648
  }
2544
2649
  case "opencode":
2545
2650
  return generateOpenCodeConfig(rules, config, baseDir);
2651
+ case "qwencode": {
2652
+ const qwenRulesOutputs = await generateQwencodeConfig2(rules, config, baseDir);
2653
+ const qwenIgnoreOutputs = await generateQwenCodeIgnoreFiles(rules, config, baseDir);
2654
+ return [...qwenRulesOutputs, ...qwenIgnoreOutputs];
2655
+ }
2546
2656
  case "windsurf": {
2547
2657
  const windsurfRulesOutputs = await generateWindsurfConfig(rules, config, baseDir);
2548
2658
  const windsurfIgnoreOutputs = await generateWindsurfIgnore(rules, config, baseDir);
@@ -2719,6 +2829,7 @@ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
2719
2829
  claudecode: ".",
2720
2830
  codexcli: ".",
2721
2831
  opencode: ".",
2832
+ qwencode: ".qwen/memories",
2722
2833
  roo: ".roo/rules",
2723
2834
  geminicli: ".gemini/memories",
2724
2835
  kiro: ".kiro/steering",
@@ -2728,41 +2839,45 @@ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
2728
2839
  watchEnabled: false,
2729
2840
  defaultTargets: []
2730
2841
  };
2731
- const results = await (await import("./amazonqcli-WVGYACHI.js")).generateAmazonqcliMcp(
2842
+ const results = await (await import("./amazonqcli-MW7XTVPN.js")).generateAmazonqcliMcp(
2732
2843
  servers,
2733
2844
  config,
2734
2845
  dir
2735
2846
  );
2736
2847
  return results.map((result) => ({ filepath: result.filepath, content: result.content }));
2737
2848
  },
2738
- augmentcode: async (servers, dir) => (await import("./augmentcode-DTHPPXWO.js")).generateAugmentcodeMcpConfiguration(
2849
+ augmentcode: async (servers, dir) => (await import("./augmentcode-WCZCL7VR.js")).generateAugmentcodeMcpConfiguration(
2850
+ servers,
2851
+ dir
2852
+ ),
2853
+ "augmentcode-legacy": async (servers, dir) => (await import("./augmentcode-WCZCL7VR.js")).generateAugmentcodeMcpConfiguration(
2739
2854
  servers,
2740
2855
  dir
2741
2856
  ),
2742
- "augmentcode-legacy": async (servers, dir) => (await import("./augmentcode-DTHPPXWO.js")).generateAugmentcodeMcpConfiguration(
2857
+ claudecode: async (servers, dir) => (await import("./claudecode-RZSJPPBU.js")).generateClaudeMcpConfiguration(
2743
2858
  servers,
2744
2859
  dir
2745
2860
  ),
2746
- claudecode: async (servers, dir) => (await import("./claudecode-SSYLLUXX.js")).generateClaudeMcpConfiguration(
2861
+ copilot: async (servers, dir) => (await import("./copilot-H3CLGKDP.js")).generateCopilotMcpConfiguration(servers, dir),
2862
+ cursor: async (servers, dir) => (await import("./cursor-ZUN5RZU6.js")).generateCursorMcpConfiguration(servers, dir),
2863
+ cline: async (servers, dir) => (await import("./cline-JTWWBQQ4.js")).generateClineMcpConfiguration(servers, dir),
2864
+ codexcli: async (servers, dir) => (await import("./codexcli-ATMFGRJR.js")).generateCodexMcpConfiguration(servers, dir),
2865
+ opencode: async (servers, dir) => (await import("./opencode-EBS3CED2.js")).generateOpenCodeMcpConfiguration(
2747
2866
  servers,
2748
2867
  dir
2749
2868
  ),
2750
- copilot: async (servers, dir) => (await import("./copilot-HSQO7ZCJ.js")).generateCopilotMcpConfiguration(servers, dir),
2751
- cursor: async (servers, dir) => (await import("./cursor-ZB3XNGBK.js")).generateCursorMcpConfiguration(servers, dir),
2752
- cline: async (servers, dir) => (await import("./cline-5EUGKNZ6.js")).generateClineMcpConfiguration(servers, dir),
2753
- codexcli: async (servers, dir) => (await import("./codexcli-IGM2ADYK.js")).generateCodexMcpConfiguration(servers, dir),
2754
- opencode: async (servers, dir) => (await import("./opencode-SZETJ62M.js")).generateOpenCodeMcpConfiguration(
2869
+ roo: async (servers, dir) => (await import("./roo-KBTRH4TZ.js")).generateRooMcpConfiguration(servers, dir),
2870
+ geminicli: async (servers, dir) => (await import("./geminicli-Q5HPIQCU.js")).generateGeminiCliMcpConfiguration(
2755
2871
  servers,
2756
2872
  dir
2757
2873
  ),
2758
- roo: async (servers, dir) => (await import("./roo-KLTWVAKE.js")).generateRooMcpConfiguration(servers, dir),
2759
- geminicli: async (servers, dir) => (await import("./geminicli-FNRKH5GX.js")).generateGeminiCliMcpConfiguration(
2874
+ kiro: async (servers, dir) => (await import("./kiro-CNF6433S.js")).generateKiroMcpConfiguration(servers, dir),
2875
+ junie: async (servers, dir) => (await import("./junie-JCLVC3MI.js")).generateJunieMcpConfiguration(servers, dir),
2876
+ qwencode: async (servers, dir) => (await import("./qwencode-JIT6KW7E.js")).generateQwenCodeMcpConfiguration(
2760
2877
  servers,
2761
2878
  dir
2762
2879
  ),
2763
- kiro: async (servers, dir) => (await import("./kiro-B6WZNLY4.js")).generateKiroMcpConfiguration(servers, dir),
2764
- junie: async (servers, dir) => (await import("./junie-3YGOSOGF.js")).generateJunieMcpConfiguration(servers, dir),
2765
- windsurf: async (servers, dir) => (await import("./windsurf-IZEKUAID.js")).generateWindsurfMcpConfiguration(
2880
+ windsurf: async (servers, dir) => (await import("./windsurf-ZAAWL6JJ.js")).generateWindsurfMcpConfiguration(
2766
2881
  servers,
2767
2882
  dir
2768
2883
  )
@@ -2791,35 +2906,40 @@ async function generateCommand(options = {}) {
2791
2906
  };
2792
2907
  const configResult = await loadConfig(configLoaderOptions);
2793
2908
  const cliOptions = {
2794
- ...options.tools !== void 0 && { tools: options.tools },
2909
+ tools: options.tools,
2795
2910
  ...options.verbose !== void 0 && { verbose: options.verbose },
2796
2911
  ...options.delete !== void 0 && { delete: options.delete },
2797
2912
  ...options.baseDirs !== void 0 && { baseDirs: options.baseDirs }
2798
2913
  };
2799
2914
  const config = mergeWithCliOptions(configResult.config, cliOptions);
2800
- logger.setVerbose(config.verbose || false);
2801
- if (options.tools && options.tools.length > 0) {
2802
- const configTargets = config.defaultTargets;
2803
- const cliTools = options.tools;
2804
- const cliToolsSet = new Set(cliTools);
2805
- const configTargetsSet = new Set(configTargets);
2806
- const notInConfig = cliTools.filter((tool) => !configTargetsSet.has(tool));
2807
- const notInCli = configTargets.filter((tool) => !cliToolsSet.has(tool));
2808
- if (notInConfig.length > 0 || notInCli.length > 0) {
2809
- logger.warn("\u26A0\uFE0F Warning: CLI tool selection differs from configuration!");
2810
- logger.warn(` Config targets: ${configTargets.join(", ")}`);
2811
- logger.warn(` CLI specified: ${cliTools.join(", ")}`);
2812
- if (notInConfig.length > 0) {
2813
- logger.warn(` Tools specified but not in config: ${notInConfig.join(", ")}`);
2814
- }
2815
- if (notInCli.length > 0) {
2816
- logger.warn(` Tools in config but not specified: ${notInCli.join(", ")}`);
2817
- }
2818
- logger.warn("\n The configuration file targets will be used.");
2819
- logger.warn(" To change targets, update your rulesync config file.");
2820
- logger.warn("");
2821
- }
2915
+ if (!config.defaultTargets || config.defaultTargets.length === 0) {
2916
+ const errorMessage = `\u274C Error: At least one tool must be specified.
2917
+
2918
+ Available tools:
2919
+ --augmentcode Generate for AugmentCode
2920
+ --augmentcode-legacy Generate for AugmentCode legacy format
2921
+ --copilot Generate for GitHub Copilot
2922
+ --cursor Generate for Cursor
2923
+ --cline Generate for Cline
2924
+ --codexcli Generate for OpenAI Codex CLI
2925
+ --claudecode Generate for Claude Code
2926
+ --roo Generate for Roo Code
2927
+ --geminicli Generate for Gemini CLI
2928
+ --junie Generate for JetBrains Junie
2929
+ --qwencode Generate for Qwen Code
2930
+ --kiro Generate for Kiro IDE
2931
+ --opencode Generate for OpenCode
2932
+ --windsurf Generate for Windsurf
2933
+
2934
+ Example:
2935
+ rulesync generate --copilot --cursor
2936
+
2937
+ Or specify tools in rulesync.jsonc:
2938
+ "tools": ["copilot", "cursor"]`;
2939
+ logger.error(errorMessage);
2940
+ process.exit(1);
2822
2941
  }
2942
+ logger.setVerbose(config.verbose || false);
2823
2943
  let baseDirs;
2824
2944
  if (config.baseDir) {
2825
2945
  baseDirs = Array.isArray(config.baseDir) ? config.baseDir : [config.baseDir];
@@ -2847,7 +2967,7 @@ async function generateCommand(options = {}) {
2847
2967
  logger.info("Deleting existing output directories...");
2848
2968
  const targetTools = config.defaultTargets;
2849
2969
  const deleteTasks = [];
2850
- const commandsDir = join12(config.aiRulesDir, "commands");
2970
+ const commandsDir = join13(config.aiRulesDir, "commands");
2851
2971
  const hasCommands = await fileExists(commandsDir);
2852
2972
  let hasCommandFiles = false;
2853
2973
  if (hasCommands) {
@@ -2862,12 +2982,12 @@ async function generateCommand(options = {}) {
2862
2982
  for (const tool of targetTools) {
2863
2983
  switch (tool) {
2864
2984
  case "augmentcode":
2865
- deleteTasks.push(removeDirectory(join12(".augment", "rules")));
2866
- deleteTasks.push(removeDirectory(join12(".augment", "ignore")));
2985
+ deleteTasks.push(removeDirectory(join13(".augment", "rules")));
2986
+ deleteTasks.push(removeDirectory(join13(".augment", "ignore")));
2867
2987
  break;
2868
2988
  case "augmentcode-legacy":
2869
2989
  deleteTasks.push(removeClaudeGeneratedFiles());
2870
- deleteTasks.push(removeDirectory(join12(".augment", "ignore")));
2990
+ deleteTasks.push(removeDirectory(join13(".augment", "ignore")));
2871
2991
  break;
2872
2992
  case "copilot":
2873
2993
  deleteTasks.push(removeDirectory(config.outputPaths.copilot));
@@ -2881,19 +3001,19 @@ async function generateCommand(options = {}) {
2881
3001
  case "claudecode":
2882
3002
  deleteTasks.push(removeClaudeGeneratedFiles());
2883
3003
  if (hasCommandFiles) {
2884
- deleteTasks.push(removeDirectory(join12(".claude", "commands")));
3004
+ deleteTasks.push(removeDirectory(join13(".claude", "commands")));
2885
3005
  }
2886
3006
  break;
2887
3007
  case "roo":
2888
3008
  deleteTasks.push(removeDirectory(config.outputPaths.roo));
2889
3009
  if (hasCommandFiles) {
2890
- deleteTasks.push(removeDirectory(join12(".roo", "commands")));
3010
+ deleteTasks.push(removeDirectory(join13(".roo", "commands")));
2891
3011
  }
2892
3012
  break;
2893
3013
  case "geminicli":
2894
3014
  deleteTasks.push(removeDirectory(config.outputPaths.geminicli));
2895
3015
  if (hasCommandFiles) {
2896
- deleteTasks.push(removeDirectory(join12(".gemini", "commands")));
3016
+ deleteTasks.push(removeDirectory(join13(".gemini", "commands")));
2897
3017
  }
2898
3018
  break;
2899
3019
  case "kiro":
@@ -2902,6 +3022,9 @@ async function generateCommand(options = {}) {
2902
3022
  case "opencode":
2903
3023
  deleteTasks.push(removeDirectory(config.outputPaths.opencode));
2904
3024
  break;
3025
+ case "qwencode":
3026
+ deleteTasks.push(removeDirectory(config.outputPaths.qwencode));
3027
+ break;
2905
3028
  case "windsurf":
2906
3029
  deleteTasks.push(removeDirectory(config.outputPaths.windsurf));
2907
3030
  break;
@@ -2995,9 +3118,9 @@ Generating configurations for base directory: ${baseDir}`);
2995
3118
 
2996
3119
  // src/cli/commands/gitignore.ts
2997
3120
  import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
2998
- import { join as join13 } from "path";
3121
+ import { join as join14 } from "path";
2999
3122
  var gitignoreCommand = async () => {
3000
- const gitignorePath = join13(process.cwd(), ".gitignore");
3123
+ const gitignorePath = join14(process.cwd(), ".gitignore");
3001
3124
  const rulesFilesToIgnore = [
3002
3125
  "# Generated by rulesync - AI tool configuration files",
3003
3126
  "**/.amazonq/rules/",
@@ -3019,6 +3142,8 @@ var gitignoreCommand = async () => {
3019
3142
  "**/GEMINI.md",
3020
3143
  "**/.gemini/memories/",
3021
3144
  "**/.gemini/commands/",
3145
+ "**/QWEN.md",
3146
+ "**/.qwen/memories/",
3022
3147
  "**/.aiexclude",
3023
3148
  "**/.aiignore",
3024
3149
  "**/.augmentignore",
@@ -3037,6 +3162,7 @@ var gitignoreCommand = async () => {
3037
3162
  "**/.vscode/mcp.json",
3038
3163
  "**/.codex/mcp-config.json",
3039
3164
  "**/.gemini/settings.json",
3165
+ "**/.qwen/settings.json",
3040
3166
  "**/.roo/mcp.json"
3041
3167
  ];
3042
3168
  let gitignoreContent = "";
@@ -3068,11 +3194,11 @@ ${linesToAdd.join("\n")}
3068
3194
  };
3069
3195
 
3070
3196
  // src/core/importer.ts
3071
- import { join as join20 } from "path";
3197
+ import { join as join21 } from "path";
3072
3198
  import matter2 from "gray-matter";
3073
3199
 
3074
3200
  // src/parsers/shared-helpers.ts
3075
- import { basename as basename3, join as join14 } from "path";
3201
+ import { basename as basename3, join as join15 } from "path";
3076
3202
  async function parseConfigurationFiles(baseDir = process.cwd(), config) {
3077
3203
  const errors = [];
3078
3204
  const rules = [];
@@ -3129,7 +3255,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
3129
3255
  const files = await readdir(dirPath);
3130
3256
  for (const file of files) {
3131
3257
  if (file.endsWith(dirConfig.filePattern)) {
3132
- const filePath = join14(dirPath, file);
3258
+ const filePath = join15(dirPath, file);
3133
3259
  const fileResult = await safeAsyncOperation(async () => {
3134
3260
  const rawContent = await readFileContent(filePath);
3135
3261
  let content;
@@ -3280,7 +3406,7 @@ async function parseMemoryFiles(memoryDir, config) {
3280
3406
  const files = await readdir(memoryDir);
3281
3407
  for (const file of files) {
3282
3408
  if (file.endsWith(".md")) {
3283
- const filePath = join14(memoryDir, file);
3409
+ const filePath = join15(memoryDir, file);
3284
3410
  const content = await readFileContent(filePath);
3285
3411
  if (content.trim()) {
3286
3412
  const filename = basename3(file, ".md");
@@ -3310,7 +3436,7 @@ async function parseCommandsFiles(commandsDir, config) {
3310
3436
  const files = await readdir(commandsDir);
3311
3437
  for (const file of files) {
3312
3438
  if (file.endsWith(".md")) {
3313
- const filePath = join14(commandsDir, file);
3439
+ const filePath = join15(commandsDir, file);
3314
3440
  const content = await readFileContent(filePath);
3315
3441
  if (content.trim()) {
3316
3442
  const filename = basename3(file, ".md");
@@ -3402,7 +3528,7 @@ async function parseAmazonqcliConfiguration(baseDir = process.cwd()) {
3402
3528
  }
3403
3529
 
3404
3530
  // src/parsers/augmentcode.ts
3405
- import { basename as basename4, join as join15 } from "path";
3531
+ import { basename as basename4, join as join16 } from "path";
3406
3532
 
3407
3533
  // src/utils/parser-helpers.ts
3408
3534
  function createParseResult() {
@@ -3450,7 +3576,7 @@ async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
3450
3576
  async function parseUnifiedAugmentcode(baseDir, config) {
3451
3577
  const result = createParseResult();
3452
3578
  if (config.rulesDir) {
3453
- const rulesDir = join15(baseDir, config.rulesDir);
3579
+ const rulesDir = join16(baseDir, config.rulesDir);
3454
3580
  if (await fileExists(rulesDir)) {
3455
3581
  const rulesResult = await parseAugmentRules(rulesDir, config);
3456
3582
  addRules(result, rulesResult.rules);
@@ -3463,7 +3589,7 @@ async function parseUnifiedAugmentcode(baseDir, config) {
3463
3589
  }
3464
3590
  }
3465
3591
  if (config.legacyFilePath) {
3466
- const legacyPath = join15(baseDir, config.legacyFilePath);
3592
+ const legacyPath = join16(baseDir, config.legacyFilePath);
3467
3593
  if (await fileExists(legacyPath)) {
3468
3594
  const legacyResult = await parseAugmentGuidelines(legacyPath, config);
3469
3595
  if (legacyResult.rule) {
@@ -3487,7 +3613,7 @@ async function parseAugmentRules(rulesDir, config) {
3487
3613
  const files = await readdir(rulesDir);
3488
3614
  for (const file of files) {
3489
3615
  if (file.endsWith(".md") || file.endsWith(".mdc")) {
3490
- const filePath = join15(rulesDir, file);
3616
+ const filePath = join16(rulesDir, file);
3491
3617
  try {
3492
3618
  const rawContent = await readFileContent(filePath);
3493
3619
  const parsed = parseFrontmatter(rawContent);
@@ -3587,7 +3713,7 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
3587
3713
  }
3588
3714
 
3589
3715
  // src/parsers/codexcli.ts
3590
- import { join as join16 } from "path";
3716
+ import { join as join17 } from "path";
3591
3717
 
3592
3718
  // src/parsers/copilot.ts
3593
3719
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
@@ -3610,7 +3736,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
3610
3736
  }
3611
3737
 
3612
3738
  // src/parsers/cursor.ts
3613
- import { basename as basename5, join as join17 } from "path";
3739
+ import { basename as basename5, join as join18 } from "path";
3614
3740
  import { DEFAULT_SCHEMA, FAILSAFE_SCHEMA, load } from "js-yaml";
3615
3741
  import { z as z7 } from "zod/mini";
3616
3742
  var customMatterOptions = {
@@ -3734,7 +3860,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3734
3860
  const rules = [];
3735
3861
  let ignorePatterns;
3736
3862
  let mcpServers;
3737
- const cursorFilePath = join17(baseDir, ".cursorrules");
3863
+ const cursorFilePath = join18(baseDir, ".cursorrules");
3738
3864
  if (await fileExists(cursorFilePath)) {
3739
3865
  try {
3740
3866
  const rawContent = await readFileContent(cursorFilePath);
@@ -3755,14 +3881,14 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3755
3881
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
3756
3882
  }
3757
3883
  }
3758
- const cursorRulesDir = join17(baseDir, ".cursor", "rules");
3884
+ const cursorRulesDir = join18(baseDir, ".cursor", "rules");
3759
3885
  if (await fileExists(cursorRulesDir)) {
3760
3886
  try {
3761
3887
  const { readdir } = await import("fs/promises");
3762
3888
  const files = await readdir(cursorRulesDir);
3763
3889
  for (const file of files) {
3764
3890
  if (file.endsWith(".mdc")) {
3765
- const filePath = join17(cursorRulesDir, file);
3891
+ const filePath = join18(cursorRulesDir, file);
3766
3892
  try {
3767
3893
  const rawContent = await readFileContent(filePath);
3768
3894
  const parsed = parseFrontmatter(rawContent, { matterOptions: customMatterOptions });
@@ -3791,7 +3917,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3791
3917
  if (rules.length === 0) {
3792
3918
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
3793
3919
  }
3794
- const cursorIgnorePath = join17(baseDir, ".cursorignore");
3920
+ const cursorIgnorePath = join18(baseDir, ".cursorignore");
3795
3921
  if (await fileExists(cursorIgnorePath)) {
3796
3922
  try {
3797
3923
  const content = await readFileContent(cursorIgnorePath);
@@ -3804,7 +3930,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
3804
3930
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
3805
3931
  }
3806
3932
  }
3807
- const cursorMcpPath = join17(baseDir, ".cursor", "mcp.json");
3933
+ const cursorMcpPath = join18(baseDir, ".cursor", "mcp.json");
3808
3934
  if (await fileExists(cursorMcpPath)) {
3809
3935
  try {
3810
3936
  const content = await readFileContent(cursorMcpPath);
@@ -3854,11 +3980,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
3854
3980
  }
3855
3981
 
3856
3982
  // src/parsers/junie.ts
3857
- import { join as join18 } from "path";
3983
+ import { join as join19 } from "path";
3858
3984
  async function parseJunieConfiguration(baseDir = process.cwd()) {
3859
3985
  const errors = [];
3860
3986
  const rules = [];
3861
- const guidelinesPath = join18(baseDir, ".junie", "guidelines.md");
3987
+ const guidelinesPath = join19(baseDir, ".junie", "guidelines.md");
3862
3988
  if (!await fileExists(guidelinesPath)) {
3863
3989
  errors.push(".junie/guidelines.md file not found");
3864
3990
  return { rules, errors };
@@ -3915,6 +4041,22 @@ async function parseOpenCodeConfiguration(baseDir = process.cwd()) {
3915
4041
  });
3916
4042
  }
3917
4043
 
4044
+ // src/parsers/qwencode.ts
4045
+ async function parseQwenConfiguration(baseDir = process.cwd()) {
4046
+ return parseMemoryBasedConfiguration(baseDir, {
4047
+ tool: "qwencode",
4048
+ mainFileName: "QWEN.md",
4049
+ memoryDirPath: ".qwen/memories",
4050
+ settingsPath: ".qwen/settings.json",
4051
+ mainDescription: "Main Qwen Code configuration",
4052
+ memoryDescription: "Memory file",
4053
+ filenamePrefix: "qwen",
4054
+ // Qwen Code uses git-aware filtering instead of dedicated ignore files
4055
+ // additionalIgnoreFile is omitted
4056
+ commandsDirPath: ".qwen/commands"
4057
+ });
4058
+ }
4059
+
3918
4060
  // src/parsers/roo.ts
3919
4061
  async function parseRooConfiguration(baseDir = process.cwd()) {
3920
4062
  return parseConfigurationFiles(baseDir, {
@@ -3937,7 +4079,7 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
3937
4079
 
3938
4080
  // src/parsers/windsurf.ts
3939
4081
  import { readFile } from "fs/promises";
3940
- import { join as join19 } from "path";
4082
+ import { join as join20 } from "path";
3941
4083
 
3942
4084
  // src/core/importer.ts
3943
4085
  async function importConfiguration(options) {
@@ -4032,6 +4174,13 @@ async function importConfiguration(options) {
4032
4174
  mcpServers = opencodeResult.mcpServers;
4033
4175
  break;
4034
4176
  }
4177
+ case "qwencode": {
4178
+ const qwenResult = await parseQwenConfiguration(baseDir);
4179
+ rules = qwenResult.rules;
4180
+ errors.push(...qwenResult.errors);
4181
+ mcpServers = qwenResult.mcpServers;
4182
+ break;
4183
+ }
4035
4184
  default:
4036
4185
  errors.push(`Unsupported tool: ${tool}`);
4037
4186
  return { success: false, rulesCreated: 0, errors };
@@ -4044,7 +4193,7 @@ async function importConfiguration(options) {
4044
4193
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
4045
4194
  return { success: false, rulesCreated: 0, errors };
4046
4195
  }
4047
- const rulesDirPath = join20(baseDir, rulesDir);
4196
+ const rulesDirPath = join21(baseDir, rulesDir);
4048
4197
  try {
4049
4198
  const { mkdir: mkdir2 } = await import("fs/promises");
4050
4199
  await mkdir2(rulesDirPath, { recursive: true });
@@ -4059,17 +4208,17 @@ async function importConfiguration(options) {
4059
4208
  const baseFilename = rule.filename;
4060
4209
  let targetDir = rulesDirPath;
4061
4210
  if (rule.type === "command") {
4062
- targetDir = join20(rulesDirPath, "commands");
4211
+ targetDir = join21(rulesDirPath, "commands");
4063
4212
  const { mkdir: mkdir2 } = await import("fs/promises");
4064
4213
  await mkdir2(targetDir, { recursive: true });
4065
4214
  } else {
4066
4215
  if (!useLegacyLocation) {
4067
- targetDir = join20(rulesDirPath, "rules");
4216
+ targetDir = join21(rulesDirPath, "rules");
4068
4217
  const { mkdir: mkdir2 } = await import("fs/promises");
4069
4218
  await mkdir2(targetDir, { recursive: true });
4070
4219
  }
4071
4220
  }
4072
- const filePath = join20(targetDir, `${baseFilename}.md`);
4221
+ const filePath = join21(targetDir, `${baseFilename}.md`);
4073
4222
  const content = generateRuleFileContent(rule);
4074
4223
  await writeFileContent(filePath, content);
4075
4224
  rulesCreated++;
@@ -4084,7 +4233,7 @@ async function importConfiguration(options) {
4084
4233
  let ignoreFileCreated = false;
4085
4234
  if (ignorePatterns && ignorePatterns.length > 0) {
4086
4235
  try {
4087
- const rulesyncignorePath = join20(baseDir, ".rulesyncignore");
4236
+ const rulesyncignorePath = join21(baseDir, ".rulesyncignore");
4088
4237
  const ignoreContent = `${ignorePatterns.join("\n")}
4089
4238
  `;
4090
4239
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -4100,7 +4249,7 @@ async function importConfiguration(options) {
4100
4249
  let mcpFileCreated = false;
4101
4250
  if (mcpServers && Object.keys(mcpServers).length > 0) {
4102
4251
  try {
4103
- const mcpPath = join20(baseDir, rulesDir, ".mcp.json");
4252
+ const mcpPath = join21(baseDir, rulesDir, ".mcp.json");
4104
4253
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
4105
4254
  `;
4106
4255
  await writeFileContent(mcpPath, mcpContent);
@@ -4147,10 +4296,11 @@ async function importCommand(options = {}) {
4147
4296
  if (options.cline) tools.push("cline");
4148
4297
  if (options.roo) tools.push("roo");
4149
4298
  if (options.geminicli) tools.push("geminicli");
4299
+ if (options.qwencode) tools.push("qwencode");
4150
4300
  if (options.opencode) tools.push("opencode");
4151
4301
  if (tools.length === 0) {
4152
4302
  logger.error(
4153
- "\u274C Please specify one tool to import from (--amazonqcli, --augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli, --opencode)"
4303
+ "\u274C Please specify one tool to import from (--amazonqcli, --augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli, --qwencode, --opencode)"
4154
4304
  );
4155
4305
  process.exit(1);
4156
4306
  }
@@ -4198,7 +4348,7 @@ async function importCommand(options = {}) {
4198
4348
  }
4199
4349
 
4200
4350
  // src/cli/commands/init.ts
4201
- import { join as join21 } from "path";
4351
+ import { join as join22 } from "path";
4202
4352
  async function initCommand(options = {}) {
4203
4353
  const configResult = await loadConfig();
4204
4354
  const config = configResult.config;
@@ -4206,7 +4356,7 @@ async function initCommand(options = {}) {
4206
4356
  logger.log("Initializing rulesync...");
4207
4357
  await ensureDir(aiRulesDir);
4208
4358
  const useLegacy = options.legacy ?? config.legacy ?? false;
4209
- const rulesDir = useLegacy ? aiRulesDir : join21(aiRulesDir, "rules");
4359
+ const rulesDir = useLegacy ? aiRulesDir : join22(aiRulesDir, "rules");
4210
4360
  if (!useLegacy) {
4211
4361
  await ensureDir(rulesDir);
4212
4362
  }
@@ -4252,7 +4402,7 @@ globs: ["**/*"]
4252
4402
  - Follow single responsibility principle
4253
4403
  `
4254
4404
  };
4255
- const filepath = join21(rulesDir, sampleFile.filename);
4405
+ const filepath = join22(rulesDir, sampleFile.filename);
4256
4406
  if (!await fileExists(filepath)) {
4257
4407
  await writeFileContent(filepath, sampleFile.content);
4258
4408
  logger.success(`Created ${filepath}`);
@@ -4396,38 +4546,41 @@ async function watchCommand() {
4396
4546
 
4397
4547
  // src/cli/index.ts
4398
4548
  var program = new Command();
4399
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.64.0");
4549
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.65.0");
4400
4550
  program.command("init").description("Initialize rulesync in current directory").option("--legacy", "Use legacy file location (.rulesync/*.md instead of .rulesync/rules/*.md)").action(initCommand);
4401
4551
  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);
4402
4552
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
4403
- 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);
4404
- 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(
4553
+ 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);
4554
+ 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(
4405
4555
  "-b, --base-dir <paths>",
4406
4556
  "Base directories to generate files (comma-separated for multiple paths)"
4407
4557
  ).option("-v, --verbose", "Verbose output").option("-c, --config <path>", "Path to configuration file").option("--no-config", "Disable configuration file loading").action(async (options) => {
4408
4558
  const tools = [];
4409
- if (options.augmentcode) tools.push("augmentcode");
4410
- if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
4411
- if (options.copilot) tools.push("copilot");
4412
- if (options.cursor) tools.push("cursor");
4413
- if (options.cline) tools.push("cline");
4414
- if (options.codexcli) tools.push("codexcli");
4415
- if (options.claudecode) tools.push("claudecode");
4416
- if (options.roo) tools.push("roo");
4417
- if (options.geminicli) tools.push("geminicli");
4418
- if (options.junie) tools.push("junie");
4419
- if (options.kiro) tools.push("kiro");
4420
- if (options.opencode) tools.push("opencode");
4421
- if (options.windsurf) tools.push("windsurf");
4559
+ if (options.all) {
4560
+ tools.push(...ALL_TOOL_TARGETS);
4561
+ } else {
4562
+ if (options.augmentcode) tools.push("augmentcode");
4563
+ if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
4564
+ if (options.copilot) tools.push("copilot");
4565
+ if (options.cursor) tools.push("cursor");
4566
+ if (options.cline) tools.push("cline");
4567
+ if (options.codexcli) tools.push("codexcli");
4568
+ if (options.claudecode) tools.push("claudecode");
4569
+ if (options.roo) tools.push("roo");
4570
+ if (options.geminicli) tools.push("geminicli");
4571
+ if (options.junie) tools.push("junie");
4572
+ if (options.qwencode) tools.push("qwencode");
4573
+ if (options.kiro) tools.push("kiro");
4574
+ if (options.opencode) tools.push("opencode");
4575
+ if (options.windsurf) tools.push("windsurf");
4576
+ }
4422
4577
  const generateOptions = {
4423
4578
  verbose: options.verbose,
4579
+ tools: tools.length > 0 ? tools : void 0,
4424
4580
  delete: options.delete,
4425
4581
  config: options.config,
4426
4582
  noConfig: options.noConfig
4427
4583
  };
4428
- if (tools.length > 0) {
4429
- generateOptions.tools = tools;
4430
- }
4431
4584
  if (options.baseDir) {
4432
4585
  generateOptions.baseDirs = options.baseDir.split(",").map((dir) => dir.trim()).filter((dir) => dir.length > 0);
4433
4586
  }