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.
- package/README.md +7 -1
- package/dist/{amazonqcli-WVGYACHI.js → amazonqcli-MW7XTVPN.js} +2 -2
- package/dist/{augmentcode-DTHPPXWO.js → augmentcode-WCZCL7VR.js} +2 -2
- package/dist/{chunk-KKWJVA56.js → chunk-4NWMCTN5.js} +1 -1
- package/dist/{chunk-DMTCLQ4T.js → chunk-6AXPFPKI.js} +1 -1
- package/dist/{chunk-EID75W45.js → chunk-6SLEITCQ.js} +1 -1
- package/dist/{chunk-YPJW7Z5M.js → chunk-DM2B7XUB.js} +1 -1
- package/dist/{chunk-JX55DU6Y.js → chunk-FL5BF6JM.js} +1 -1
- package/dist/{chunk-TBXG53FV.js → chunk-GIAQWZQ4.js} +1 -1
- package/dist/{chunk-E2J3UBBK.js → chunk-I4NVS7GE.js} +1 -1
- package/dist/{chunk-6LSN7HSJ.js → chunk-JXOLLTNV.js} +14 -1
- package/dist/{chunk-HHJIL3YZ.js → chunk-LTWEI4PW.js} +1 -1
- package/dist/{chunk-LYVES5YR.js → chunk-M2AUM37M.js} +1 -0
- package/dist/{chunk-4NAQ5HL4.js → chunk-N6DASHJL.js} +1 -1
- package/dist/chunk-TX2CE4RR.js +17 -0
- package/dist/{chunk-TQOL7OKY.js → chunk-UGY5ALND.js} +1 -1
- package/dist/{chunk-LURFNGH4.js → chunk-VRWNZTGW.js} +1 -1
- package/dist/{chunk-FVPZQEWP.js → chunk-YC2BC7Z2.js} +1 -1
- package/dist/{claudecode-SSYLLUXX.js → claudecode-RZSJPPBU.js} +3 -3
- package/dist/{cline-5EUGKNZ6.js → cline-JTWWBQQ4.js} +3 -3
- package/dist/{codexcli-IGM2ADYK.js → codexcli-ATMFGRJR.js} +3 -3
- package/dist/{copilot-HSQO7ZCJ.js → copilot-H3CLGKDP.js} +2 -2
- package/dist/{cursor-ZB3XNGBK.js → cursor-ZUN5RZU6.js} +3 -3
- package/dist/{geminicli-FNRKH5GX.js → geminicli-Q5HPIQCU.js} +3 -3
- package/dist/index.cjs +297 -111
- package/dist/index.js +286 -133
- package/dist/{junie-3YGOSOGF.js → junie-JCLVC3MI.js} +3 -3
- package/dist/{kiro-B6WZNLY4.js → kiro-CNF6433S.js} +2 -2
- package/dist/{opencode-SZETJ62M.js → opencode-EBS3CED2.js} +2 -2
- package/dist/qwencode-JIT6KW7E.js +10 -0
- package/dist/{roo-KLTWVAKE.js → roo-KBTRH4TZ.js} +3 -3
- package/dist/{windsurf-IZEKUAID.js → windsurf-ZAAWL6JJ.js} +3 -3
- 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
|
|
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
|
|
3024
|
+
var import_node_path9 = require("path");
|
|
2929
3025
|
init_file();
|
|
2930
3026
|
|
|
2931
3027
|
// src/utils/ignore.ts
|
|
2932
|
-
var
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
3548
|
+
return (0, import_node_path12.join)(outputDir, ".windsurf-rules");
|
|
3453
3549
|
} else {
|
|
3454
|
-
const rulesDir = (0,
|
|
3455
|
-
return (0,
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
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,
|
|
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,
|
|
4152
|
-
deleteTasks.push(removeDirectory((0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
4440
|
+
var import_node_path15 = require("path");
|
|
4285
4441
|
init_logger();
|
|
4286
4442
|
var gitignoreCommand = async () => {
|
|
4287
|
-
const gitignorePath = (0,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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.
|
|
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.
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
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
|
}
|