rulesync 0.55.0 → 0.56.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.ja.md +67 -5
- package/README.md +77 -6
- package/dist/{augmentcode-MJYD2Y4S.js → augmentcode-HIZIQG2W.js} +2 -2
- package/dist/chunk-7E4U4YAB.js +17 -0
- package/dist/{chunk-D7XQ4OHK.js → chunk-7UBF4OLN.js} +1 -1
- package/dist/{chunk-VI6SBYFB.js → chunk-AUUSMVCT.js} +2 -1
- package/dist/chunk-J3TBR5EP.js +292 -0
- package/dist/{chunk-OXKDEZJK.js → chunk-KUGTKMNW.js} +1 -1
- package/dist/{chunk-QVPD6ENS.js → chunk-LXTA7DBA.js} +1 -1
- package/dist/chunk-OA473EXZ.js +17 -0
- package/dist/{chunk-BEPSWIZC.js → chunk-PCATT4UZ.js} +1 -1
- package/dist/chunk-VKNCBVZF.js +17 -0
- package/dist/chunk-VNT6AHHO.js +17 -0
- package/dist/chunk-W2WU253H.js +17 -0
- package/dist/chunk-WAX2UANS.js +61 -0
- package/dist/{chunk-ORNO5MOO.js → chunk-YTU3SCQO.js} +1 -1
- package/dist/{claudecode-CKGUHLRR.js → claudecode-VVI2PTKI.js} +3 -3
- package/dist/{cline-Z5C656VR.js → cline-BJLFSLEB.js} +3 -3
- package/dist/{codexcli-VFUJKSIJ.js → codexcli-LKWQB3V3.js} +3 -3
- package/dist/{copilot-4WQS5TA7.js → copilot-MOR3HHJX.js} +2 -2
- package/dist/{cursor-HOB2F2V2.js → cursor-2BVUO64T.js} +3 -2
- package/dist/{geminicli-XTMQTIU2.js → geminicli-5YFMKRFL.js} +3 -2
- package/dist/index.cjs +532 -318
- package/dist/index.js +304 -163
- package/dist/{junie-AN6CR7DD.js → junie-5TDJPUXX.js} +3 -2
- package/dist/{kiro-PTUZOHQ2.js → kiro-YDHXY2MA.js} +2 -2
- package/dist/{roo-WOMS36KU.js → roo-L3QTTIPO.js} +2 -2
- package/dist/windsurf-PXDRIQ76.js +10 -0
- package/package.json +1 -1
- package/dist/chunk-3PHMFVXP.js +0 -66
- package/dist/chunk-OY6BYYIX.js +0 -63
- package/dist/chunk-PPAQWVXX.js +0 -94
- package/dist/chunk-TJKD6LEW.js +0 -90
- package/dist/chunk-UHANRG2O.js +0 -54
- package/dist/chunk-UZCJNUXO.js +0 -67
package/dist/index.js
CHANGED
|
@@ -1,42 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
generateJunieMcp
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VNT6AHHO.js";
|
|
5
5
|
import {
|
|
6
6
|
generateKiroMcp
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LXTA7DBA.js";
|
|
8
8
|
import {
|
|
9
9
|
generateRooMcp
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-PCATT4UZ.js";
|
|
11
|
+
import {
|
|
12
|
+
generateWindsurfMcp
|
|
13
|
+
} from "./chunk-7E4U4YAB.js";
|
|
11
14
|
import {
|
|
12
15
|
generateAugmentcodeMcp
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-YTU3SCQO.js";
|
|
14
17
|
import {
|
|
15
18
|
generateClaudeMcp
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-VKNCBVZF.js";
|
|
17
20
|
import {
|
|
18
21
|
generateClineMcp
|
|
19
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-W2WU253H.js";
|
|
20
23
|
import {
|
|
21
24
|
generateCodexMcp
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-PPAQWVXX.js";
|
|
25
|
+
} from "./chunk-7UBF4OLN.js";
|
|
24
26
|
import {
|
|
25
27
|
generateCopilotMcp
|
|
26
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-KUGTKMNW.js";
|
|
27
29
|
import {
|
|
28
30
|
generateCursorMcp
|
|
29
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-OA473EXZ.js";
|
|
30
32
|
import {
|
|
31
33
|
generateGeminiCliMcp
|
|
32
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-WAX2UANS.js";
|
|
35
|
+
import "./chunk-J3TBR5EP.js";
|
|
33
36
|
import {
|
|
34
37
|
ALL_TOOL_TARGETS,
|
|
35
38
|
RulesyncTargetsSchema,
|
|
36
39
|
ToolTargetSchema,
|
|
37
40
|
ToolTargetsSchema,
|
|
38
41
|
isToolTarget
|
|
39
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-AUUSMVCT.js";
|
|
40
43
|
|
|
41
44
|
// src/cli/index.ts
|
|
42
45
|
import { Command } from "commander";
|
|
@@ -60,7 +63,8 @@ function getDefaultConfig() {
|
|
|
60
63
|
roo: ".roo/rules",
|
|
61
64
|
geminicli: ".gemini/memories",
|
|
62
65
|
kiro: ".kiro/steering",
|
|
63
|
-
junie: "."
|
|
66
|
+
junie: ".",
|
|
67
|
+
windsurf: "."
|
|
64
68
|
},
|
|
65
69
|
watchEnabled: false,
|
|
66
70
|
defaultTargets: ALL_TOOL_TARGETS.filter((tool) => tool !== "augmentcode-legacy")
|
|
@@ -147,7 +151,8 @@ var OutputPathsSchema = z3.object({
|
|
|
147
151
|
roo: z3.optional(z3.string()),
|
|
148
152
|
geminicli: z3.optional(z3.string()),
|
|
149
153
|
kiro: z3.optional(z3.string()),
|
|
150
|
-
junie: z3.optional(z3.string())
|
|
154
|
+
junie: z3.optional(z3.string()),
|
|
155
|
+
windsurf: z3.optional(z3.string())
|
|
151
156
|
});
|
|
152
157
|
var ConfigOptionsSchema = z3.object({
|
|
153
158
|
aiRulesDir: z3.optional(z3.string()),
|
|
@@ -227,6 +232,8 @@ var RuleFrontmatterSchema = z5.object({
|
|
|
227
232
|
description: z5.string(),
|
|
228
233
|
globs: z5.array(z5.string()),
|
|
229
234
|
cursorRuleType: z5.optional(z5.enum(["always", "manual", "specificFiles", "intelligently"])),
|
|
235
|
+
windsurfActivationMode: z5.optional(z5.enum(["always", "manual", "model-decision", "glob"])),
|
|
236
|
+
windsurfOutputFormat: z5.optional(z5.enum(["single-file", "directory"])),
|
|
230
237
|
tags: z5.optional(z5.array(z5.string()))
|
|
231
238
|
});
|
|
232
239
|
var ParsedRuleSchema = z5.object({
|
|
@@ -768,7 +775,7 @@ export default config;
|
|
|
768
775
|
}
|
|
769
776
|
|
|
770
777
|
// src/cli/commands/generate.ts
|
|
771
|
-
import { join as
|
|
778
|
+
import { join as join11 } from "path";
|
|
772
779
|
|
|
773
780
|
// src/generators/ignore/shared-factory.ts
|
|
774
781
|
import { join as join3 } from "path";
|
|
@@ -1328,6 +1335,131 @@ var ignoreConfigs = {
|
|
|
1328
1335
|
],
|
|
1329
1336
|
includeCommonPatterns: false,
|
|
1330
1337
|
projectPatternsHeader: "# \u2500\u2500\u2500\u2500\u2500 Project-specific patterns from rulesync rules \u2500\u2500\u2500\u2500\u2500"
|
|
1338
|
+
},
|
|
1339
|
+
windsurf: {
|
|
1340
|
+
tool: "windsurf",
|
|
1341
|
+
filename: ".codeiumignore",
|
|
1342
|
+
header: [
|
|
1343
|
+
"# Generated by rulesync - Windsurf AI Code Editor ignore file",
|
|
1344
|
+
"# This file controls which files are excluded from Cascade AI analysis and context",
|
|
1345
|
+
"# Uses same syntax as .gitignore patterns",
|
|
1346
|
+
"# Note: Git-ignored files are automatically excluded by Windsurf"
|
|
1347
|
+
],
|
|
1348
|
+
corePatterns: [
|
|
1349
|
+
"# \u2500\u2500\u2500\u2500\u2500 Security & Credentials (Critical) \u2500\u2500\u2500\u2500\u2500",
|
|
1350
|
+
"# Environment files",
|
|
1351
|
+
".env*",
|
|
1352
|
+
"!.env.example",
|
|
1353
|
+
"",
|
|
1354
|
+
"# Private keys and certificates",
|
|
1355
|
+
"*.pem",
|
|
1356
|
+
"*.key",
|
|
1357
|
+
"*.crt",
|
|
1358
|
+
"*.p12",
|
|
1359
|
+
"*.pfx",
|
|
1360
|
+
"*.der",
|
|
1361
|
+
"",
|
|
1362
|
+
"# SSH keys",
|
|
1363
|
+
"id_rsa*",
|
|
1364
|
+
"id_dsa*",
|
|
1365
|
+
"*.ppk",
|
|
1366
|
+
"",
|
|
1367
|
+
"# API keys and tokens",
|
|
1368
|
+
"**/apikeys/",
|
|
1369
|
+
"**/*_token*",
|
|
1370
|
+
"**/*_secret*",
|
|
1371
|
+
"**/*api_key*",
|
|
1372
|
+
"",
|
|
1373
|
+
"# Cloud provider credentials",
|
|
1374
|
+
"aws-credentials.json",
|
|
1375
|
+
"gcp-service-account*.json",
|
|
1376
|
+
"azure-credentials.json",
|
|
1377
|
+
"",
|
|
1378
|
+
"# \u2500\u2500\u2500\u2500\u2500 Database & Configuration Files \u2500\u2500\u2500\u2500\u2500",
|
|
1379
|
+
"# Database files",
|
|
1380
|
+
"*.db",
|
|
1381
|
+
"*.sqlite",
|
|
1382
|
+
"*.sqlite3",
|
|
1383
|
+
"",
|
|
1384
|
+
"# Configuration files with secrets",
|
|
1385
|
+
"config/secrets/",
|
|
1386
|
+
"**/database.yml",
|
|
1387
|
+
"",
|
|
1388
|
+
"# \u2500\u2500\u2500\u2500\u2500 Build Artifacts & Dependencies \u2500\u2500\u2500\u2500\u2500",
|
|
1389
|
+
"# Build outputs",
|
|
1390
|
+
"dist/",
|
|
1391
|
+
"build/",
|
|
1392
|
+
"out/",
|
|
1393
|
+
"target/",
|
|
1394
|
+
"",
|
|
1395
|
+
"# Dependencies (already auto-excluded but reinforced)",
|
|
1396
|
+
"node_modules/",
|
|
1397
|
+
".pnpm-store/",
|
|
1398
|
+
".yarn/",
|
|
1399
|
+
"vendor/",
|
|
1400
|
+
"",
|
|
1401
|
+
"# \u2500\u2500\u2500\u2500\u2500 Cache & Temporary Files \u2500\u2500\u2500\u2500\u2500",
|
|
1402
|
+
"# Cache directories",
|
|
1403
|
+
".cache/",
|
|
1404
|
+
".parcel-cache/",
|
|
1405
|
+
".next/cache/",
|
|
1406
|
+
"",
|
|
1407
|
+
"# Temporary files",
|
|
1408
|
+
"*.tmp",
|
|
1409
|
+
"*.swp",
|
|
1410
|
+
"*.swo",
|
|
1411
|
+
"*~",
|
|
1412
|
+
"",
|
|
1413
|
+
"# \u2500\u2500\u2500\u2500\u2500 Large Data Files \u2500\u2500\u2500\u2500\u2500",
|
|
1414
|
+
"# Data files",
|
|
1415
|
+
"*.csv",
|
|
1416
|
+
"*.xlsx",
|
|
1417
|
+
"*.json",
|
|
1418
|
+
"data/",
|
|
1419
|
+
"datasets/",
|
|
1420
|
+
"",
|
|
1421
|
+
"# Media files",
|
|
1422
|
+
"*.mp4",
|
|
1423
|
+
"*.avi",
|
|
1424
|
+
"*.mov",
|
|
1425
|
+
"*.png",
|
|
1426
|
+
"*.jpg",
|
|
1427
|
+
"*.jpeg",
|
|
1428
|
+
"*.gif",
|
|
1429
|
+
"",
|
|
1430
|
+
"# Archives",
|
|
1431
|
+
"*.zip",
|
|
1432
|
+
"*.tar.gz",
|
|
1433
|
+
"*.rar",
|
|
1434
|
+
"",
|
|
1435
|
+
"# \u2500\u2500\u2500\u2500\u2500 IDE & Editor Files \u2500\u2500\u2500\u2500\u2500",
|
|
1436
|
+
"# IDE settings (personal)",
|
|
1437
|
+
".vscode/settings.json",
|
|
1438
|
+
".idea/",
|
|
1439
|
+
"",
|
|
1440
|
+
"# Editor temporary files",
|
|
1441
|
+
"*.swp",
|
|
1442
|
+
"*.swo",
|
|
1443
|
+
"",
|
|
1444
|
+
"# \u2500\u2500\u2500\u2500\u2500 Test Coverage & Logs \u2500\u2500\u2500\u2500\u2500",
|
|
1445
|
+
"# Test coverage reports",
|
|
1446
|
+
"coverage/",
|
|
1447
|
+
".nyc_output/",
|
|
1448
|
+
"",
|
|
1449
|
+
"# Logs",
|
|
1450
|
+
"*.log",
|
|
1451
|
+
"",
|
|
1452
|
+
"# \u2500\u2500\u2500\u2500\u2500 Re-include Important Files \u2500\u2500\u2500\u2500\u2500",
|
|
1453
|
+
"# Allow configuration examples",
|
|
1454
|
+
"!.env.example",
|
|
1455
|
+
"!config/*.example.*",
|
|
1456
|
+
"",
|
|
1457
|
+
"# Allow documentation",
|
|
1458
|
+
"!docs/**/*.md",
|
|
1459
|
+
"!README.md"
|
|
1460
|
+
],
|
|
1461
|
+
includeCommonPatterns: false,
|
|
1462
|
+
projectPatternsHeader: "# \u2500\u2500\u2500\u2500\u2500 Project-specific patterns from rulesync rules \u2500\u2500\u2500\u2500\u2500"
|
|
1331
1463
|
}
|
|
1332
1464
|
};
|
|
1333
1465
|
|
|
@@ -1346,6 +1478,11 @@ async function generateKiroIgnoreFiles(rules, config, baseDir) {
|
|
|
1346
1478
|
return generateIgnoreFile(rules, config, ignoreConfigs.kiro, baseDir);
|
|
1347
1479
|
}
|
|
1348
1480
|
|
|
1481
|
+
// src/generators/ignore/windsurf.ts
|
|
1482
|
+
function generateWindsurfIgnore(rules, config, baseDir) {
|
|
1483
|
+
return generateIgnoreFile(rules, config, ignoreConfigs.windsurf, baseDir);
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1349
1486
|
// src/generators/rules/augmentcode.ts
|
|
1350
1487
|
import { join as join6 } from "path";
|
|
1351
1488
|
|
|
@@ -1502,16 +1639,6 @@ function generateIgnoreFile2(patterns, tool) {
|
|
|
1502
1639
|
lines.push(...patterns);
|
|
1503
1640
|
return lines.join("\n");
|
|
1504
1641
|
}
|
|
1505
|
-
async function generateComplexRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
1506
|
-
const unifiedConfig = {
|
|
1507
|
-
tool: generatorConfig.tool,
|
|
1508
|
-
fileExtension: generatorConfig.fileExtension,
|
|
1509
|
-
ignoreFileName: generatorConfig.ignoreFileName,
|
|
1510
|
-
generateContent: generatorConfig.generateContent,
|
|
1511
|
-
pathResolver: generatorConfig.getOutputPath
|
|
1512
|
-
};
|
|
1513
|
-
return generateRulesConfig(rules, config, unifiedConfig, baseDir);
|
|
1514
|
-
}
|
|
1515
1642
|
|
|
1516
1643
|
// src/generators/rules/augmentcode.ts
|
|
1517
1644
|
async function generateAugmentcodeConfig(rules, config, baseDir) {
|
|
@@ -1582,7 +1709,7 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
|
1582
1709
|
fileExtension: ".md",
|
|
1583
1710
|
ignoreFileName: ".aiignore",
|
|
1584
1711
|
generateContent: generateMemoryFile,
|
|
1585
|
-
generateRootContent:
|
|
1712
|
+
generateRootContent: generateClaudeMarkdown,
|
|
1586
1713
|
rootFilePath: "CLAUDE.md",
|
|
1587
1714
|
generateDetailContent: generateMemoryFile,
|
|
1588
1715
|
detailSubDir: ".claude/memories",
|
|
@@ -1594,7 +1721,7 @@ async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
|
1594
1721
|
};
|
|
1595
1722
|
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
1596
1723
|
}
|
|
1597
|
-
function generateClaudeMarkdown(
|
|
1724
|
+
function generateClaudeMarkdown(rootRule, detailRules) {
|
|
1598
1725
|
const lines = [];
|
|
1599
1726
|
if (detailRules.length > 0) {
|
|
1600
1727
|
lines.push("Please also reference the following documents as needed:");
|
|
@@ -1608,11 +1735,9 @@ function generateClaudeMarkdown(rootRules, detailRules) {
|
|
|
1608
1735
|
}
|
|
1609
1736
|
lines.push("");
|
|
1610
1737
|
}
|
|
1611
|
-
if (
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
lines.push("");
|
|
1615
|
-
}
|
|
1738
|
+
if (rootRule) {
|
|
1739
|
+
lines.push(rootRule.content);
|
|
1740
|
+
lines.push("");
|
|
1616
1741
|
}
|
|
1617
1742
|
return lines.join("\n");
|
|
1618
1743
|
}
|
|
@@ -1654,6 +1779,27 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
|
|
|
1654
1779
|
|
|
1655
1780
|
// src/generators/rules/generator-registry.ts
|
|
1656
1781
|
import { join as join8 } from "path";
|
|
1782
|
+
function determineCursorRuleType(frontmatter) {
|
|
1783
|
+
if (frontmatter.cursorRuleType) {
|
|
1784
|
+
return frontmatter.cursorRuleType;
|
|
1785
|
+
}
|
|
1786
|
+
const isDescriptionEmpty = !frontmatter.description || frontmatter.description.trim() === "";
|
|
1787
|
+
const isGlobsEmpty = frontmatter.globs.length === 0;
|
|
1788
|
+
const isGlobsExactlyAllFiles = frontmatter.globs.length === 1 && frontmatter.globs[0] === "**/*";
|
|
1789
|
+
if (isGlobsExactlyAllFiles) {
|
|
1790
|
+
return "always";
|
|
1791
|
+
}
|
|
1792
|
+
if (isDescriptionEmpty && isGlobsEmpty) {
|
|
1793
|
+
return "manual";
|
|
1794
|
+
}
|
|
1795
|
+
if (isDescriptionEmpty && !isGlobsEmpty) {
|
|
1796
|
+
return "specificFiles";
|
|
1797
|
+
}
|
|
1798
|
+
if (!isDescriptionEmpty && isGlobsEmpty) {
|
|
1799
|
+
return "intelligently";
|
|
1800
|
+
}
|
|
1801
|
+
return "intelligently";
|
|
1802
|
+
}
|
|
1657
1803
|
var GENERATOR_REGISTRY = {
|
|
1658
1804
|
// Simple generators - generate one file per rule
|
|
1659
1805
|
cline: {
|
|
@@ -1718,9 +1864,42 @@ var GENERATOR_REGISTRY = {
|
|
|
1718
1864
|
cursor: {
|
|
1719
1865
|
type: "simple",
|
|
1720
1866
|
tool: "cursor",
|
|
1721
|
-
fileExtension: ".
|
|
1867
|
+
fileExtension: ".mdc",
|
|
1722
1868
|
ignoreFileName: ".cursorignore",
|
|
1723
|
-
generateContent: (rule) =>
|
|
1869
|
+
generateContent: (rule) => {
|
|
1870
|
+
const lines = [];
|
|
1871
|
+
const ruleType = determineCursorRuleType(rule.frontmatter);
|
|
1872
|
+
lines.push("---");
|
|
1873
|
+
switch (ruleType) {
|
|
1874
|
+
case "always":
|
|
1875
|
+
lines.push("description:");
|
|
1876
|
+
lines.push("globs:");
|
|
1877
|
+
lines.push("alwaysApply: true");
|
|
1878
|
+
break;
|
|
1879
|
+
case "manual":
|
|
1880
|
+
lines.push("description:");
|
|
1881
|
+
lines.push("globs:");
|
|
1882
|
+
lines.push("alwaysApply: false");
|
|
1883
|
+
break;
|
|
1884
|
+
case "specificFiles":
|
|
1885
|
+
lines.push("description:");
|
|
1886
|
+
lines.push(`globs: ${rule.frontmatter.globs.join(",")}`);
|
|
1887
|
+
lines.push("alwaysApply: false");
|
|
1888
|
+
break;
|
|
1889
|
+
case "intelligently":
|
|
1890
|
+
lines.push(`description: ${rule.frontmatter.description}`);
|
|
1891
|
+
lines.push("globs:");
|
|
1892
|
+
lines.push("alwaysApply: false");
|
|
1893
|
+
break;
|
|
1894
|
+
}
|
|
1895
|
+
lines.push("---");
|
|
1896
|
+
lines.push("");
|
|
1897
|
+
lines.push(rule.content);
|
|
1898
|
+
return lines.join("\n");
|
|
1899
|
+
},
|
|
1900
|
+
pathResolver: (rule, outputDir) => {
|
|
1901
|
+
return join8(outputDir, `${rule.filename}.mdc`);
|
|
1902
|
+
}
|
|
1724
1903
|
},
|
|
1725
1904
|
codexcli: {
|
|
1726
1905
|
type: "simple",
|
|
@@ -1729,6 +1908,39 @@ var GENERATOR_REGISTRY = {
|
|
|
1729
1908
|
ignoreFileName: ".codexignore",
|
|
1730
1909
|
generateContent: (rule) => rule.content.trim()
|
|
1731
1910
|
},
|
|
1911
|
+
windsurf: {
|
|
1912
|
+
type: "simple",
|
|
1913
|
+
tool: "windsurf",
|
|
1914
|
+
fileExtension: ".md",
|
|
1915
|
+
ignoreFileName: ".codeiumignore",
|
|
1916
|
+
generateContent: (rule) => {
|
|
1917
|
+
const lines = [];
|
|
1918
|
+
const activationMode = rule.frontmatter.windsurfActivationMode;
|
|
1919
|
+
const globPattern = rule.frontmatter.globs?.[0];
|
|
1920
|
+
if (activationMode || globPattern) {
|
|
1921
|
+
lines.push("---");
|
|
1922
|
+
if (activationMode) {
|
|
1923
|
+
lines.push(`activation: ${activationMode}`);
|
|
1924
|
+
}
|
|
1925
|
+
if (globPattern && activationMode === "glob") {
|
|
1926
|
+
lines.push(`pattern: "${globPattern}"`);
|
|
1927
|
+
}
|
|
1928
|
+
lines.push("---");
|
|
1929
|
+
lines.push("");
|
|
1930
|
+
}
|
|
1931
|
+
lines.push(rule.content.trim());
|
|
1932
|
+
return lines.join("\n");
|
|
1933
|
+
},
|
|
1934
|
+
pathResolver: (rule, outputDir) => {
|
|
1935
|
+
const outputFormat = rule.frontmatter.windsurfOutputFormat || "directory";
|
|
1936
|
+
if (outputFormat === "single-file") {
|
|
1937
|
+
return join8(outputDir, ".windsurf-rules");
|
|
1938
|
+
} else {
|
|
1939
|
+
const rulesDir = join8(outputDir, ".windsurf", "rules");
|
|
1940
|
+
return join8(rulesDir, `${rule.filename}.md`);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
},
|
|
1732
1944
|
// Complex generators with root + detail pattern
|
|
1733
1945
|
claudecode: {
|
|
1734
1946
|
type: "complex",
|
|
@@ -1867,107 +2079,13 @@ function generateConcatenatedCodexContent(rules) {
|
|
|
1867
2079
|
}
|
|
1868
2080
|
|
|
1869
2081
|
// src/generators/rules/copilot.ts
|
|
1870
|
-
import { join as join9 } from "path";
|
|
1871
2082
|
async function generateCopilotConfig(rules, config, baseDir) {
|
|
1872
|
-
return
|
|
1873
|
-
rules,
|
|
1874
|
-
config,
|
|
1875
|
-
{
|
|
1876
|
-
tool: "copilot",
|
|
1877
|
-
fileExtension: ".instructions.md",
|
|
1878
|
-
ignoreFileName: ".copilotignore",
|
|
1879
|
-
generateContent: generateCopilotMarkdown,
|
|
1880
|
-
getOutputPath: (rule, outputDir) => {
|
|
1881
|
-
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
1882
|
-
return join9(outputDir, `${baseFilename}.instructions.md`);
|
|
1883
|
-
}
|
|
1884
|
-
},
|
|
1885
|
-
baseDir
|
|
1886
|
-
);
|
|
1887
|
-
}
|
|
1888
|
-
function generateCopilotMarkdown(rule) {
|
|
1889
|
-
const lines = [];
|
|
1890
|
-
lines.push("---");
|
|
1891
|
-
lines.push(`description: "${rule.frontmatter.description}"`);
|
|
1892
|
-
if (rule.frontmatter.globs.length > 0) {
|
|
1893
|
-
lines.push(`applyTo: "${rule.frontmatter.globs.join(", ")}"`);
|
|
1894
|
-
} else {
|
|
1895
|
-
lines.push('applyTo: "**"');
|
|
1896
|
-
}
|
|
1897
|
-
lines.push("---");
|
|
1898
|
-
lines.push(rule.content);
|
|
1899
|
-
return lines.join("\n");
|
|
2083
|
+
return generateFromRegistry("copilot", rules, config, baseDir);
|
|
1900
2084
|
}
|
|
1901
2085
|
|
|
1902
2086
|
// src/generators/rules/cursor.ts
|
|
1903
|
-
import { join as join10 } from "path";
|
|
1904
2087
|
async function generateCursorConfig(rules, config, baseDir) {
|
|
1905
|
-
return
|
|
1906
|
-
rules,
|
|
1907
|
-
config,
|
|
1908
|
-
{
|
|
1909
|
-
tool: "cursor",
|
|
1910
|
-
fileExtension: ".mdc",
|
|
1911
|
-
ignoreFileName: ".cursorignore",
|
|
1912
|
-
generateContent: generateCursorMarkdown,
|
|
1913
|
-
getOutputPath: (rule, outputDir) => {
|
|
1914
|
-
return join10(outputDir, `${rule.filename}.mdc`);
|
|
1915
|
-
}
|
|
1916
|
-
},
|
|
1917
|
-
baseDir
|
|
1918
|
-
);
|
|
1919
|
-
}
|
|
1920
|
-
function generateCursorMarkdown(rule) {
|
|
1921
|
-
const lines = [];
|
|
1922
|
-
const ruleType = determineCursorRuleType(rule.frontmatter);
|
|
1923
|
-
lines.push("---");
|
|
1924
|
-
switch (ruleType) {
|
|
1925
|
-
case "always":
|
|
1926
|
-
lines.push("description:");
|
|
1927
|
-
lines.push("globs:");
|
|
1928
|
-
lines.push("alwaysApply: true");
|
|
1929
|
-
break;
|
|
1930
|
-
case "manual":
|
|
1931
|
-
lines.push("description:");
|
|
1932
|
-
lines.push("globs:");
|
|
1933
|
-
lines.push("alwaysApply: false");
|
|
1934
|
-
break;
|
|
1935
|
-
case "specificFiles":
|
|
1936
|
-
lines.push("description:");
|
|
1937
|
-
lines.push(`globs: ${rule.frontmatter.globs.join(",")}`);
|
|
1938
|
-
lines.push("alwaysApply: false");
|
|
1939
|
-
break;
|
|
1940
|
-
case "intelligently":
|
|
1941
|
-
lines.push(`description: ${rule.frontmatter.description}`);
|
|
1942
|
-
lines.push("globs:");
|
|
1943
|
-
lines.push("alwaysApply: false");
|
|
1944
|
-
break;
|
|
1945
|
-
}
|
|
1946
|
-
lines.push("---");
|
|
1947
|
-
lines.push("");
|
|
1948
|
-
lines.push(rule.content);
|
|
1949
|
-
return lines.join("\n");
|
|
1950
|
-
}
|
|
1951
|
-
function determineCursorRuleType(frontmatter) {
|
|
1952
|
-
if (frontmatter.cursorRuleType) {
|
|
1953
|
-
return frontmatter.cursorRuleType;
|
|
1954
|
-
}
|
|
1955
|
-
const isDescriptionEmpty = !frontmatter.description || frontmatter.description.trim() === "";
|
|
1956
|
-
const isGlobsEmpty = frontmatter.globs.length === 0;
|
|
1957
|
-
const isGlobsExactlyAllFiles = frontmatter.globs.length === 1 && frontmatter.globs[0] === "**/*";
|
|
1958
|
-
if (isGlobsExactlyAllFiles) {
|
|
1959
|
-
return "always";
|
|
1960
|
-
}
|
|
1961
|
-
if (isDescriptionEmpty && isGlobsEmpty) {
|
|
1962
|
-
return "manual";
|
|
1963
|
-
}
|
|
1964
|
-
if (isDescriptionEmpty && !isGlobsEmpty) {
|
|
1965
|
-
return "specificFiles";
|
|
1966
|
-
}
|
|
1967
|
-
if (!isDescriptionEmpty && isGlobsEmpty) {
|
|
1968
|
-
return "intelligently";
|
|
1969
|
-
}
|
|
1970
|
-
return "intelligently";
|
|
2088
|
+
return generateFromRegistry("cursor", rules, config, baseDir);
|
|
1971
2089
|
}
|
|
1972
2090
|
|
|
1973
2091
|
// src/generators/rules/geminicli.ts
|
|
@@ -2049,6 +2167,11 @@ async function generateRooConfig(rules, config, baseDir) {
|
|
|
2049
2167
|
return generateFromRegistry("roo", rules, config, baseDir);
|
|
2050
2168
|
}
|
|
2051
2169
|
|
|
2170
|
+
// src/generators/rules/windsurf.ts
|
|
2171
|
+
async function generateWindsurfConfig(rules, config, baseDir) {
|
|
2172
|
+
return generateFromRegistry("windsurf", rules, config, baseDir);
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2052
2175
|
// src/core/generator.ts
|
|
2053
2176
|
async function generateConfigurations(rules, config, targetTools, baseDir) {
|
|
2054
2177
|
const outputs = createOutputsArray();
|
|
@@ -2121,6 +2244,11 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
2121
2244
|
const kiroIgnoreOutputs = await generateKiroIgnoreFiles(rules, config, baseDir);
|
|
2122
2245
|
return [...kiroRulesOutputs, ...kiroIgnoreOutputs];
|
|
2123
2246
|
}
|
|
2247
|
+
case "windsurf": {
|
|
2248
|
+
const windsurfRulesOutputs = await generateWindsurfConfig(rules, config, baseDir);
|
|
2249
|
+
const windsurfIgnoreOutputs = await generateWindsurfIgnore(rules, config, baseDir);
|
|
2250
|
+
return [...windsurfRulesOutputs, ...windsurfIgnoreOutputs];
|
|
2251
|
+
}
|
|
2124
2252
|
default:
|
|
2125
2253
|
console.warn(`Unknown tool: ${tool}`);
|
|
2126
2254
|
return null;
|
|
@@ -2323,6 +2451,11 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2323
2451
|
tool: "roo-project",
|
|
2324
2452
|
path: path4.join(targetRoot, ".roo", "mcp.json"),
|
|
2325
2453
|
generate: () => generateRooMcp(config)
|
|
2454
|
+
},
|
|
2455
|
+
{
|
|
2456
|
+
tool: "windsurf-project",
|
|
2457
|
+
path: path4.join(targetRoot, "mcp_config.json"),
|
|
2458
|
+
generate: () => generateWindsurfMcp(config)
|
|
2326
2459
|
}
|
|
2327
2460
|
];
|
|
2328
2461
|
const filteredGenerators = targetTools ? generators.filter((g) => {
|
|
@@ -2339,7 +2472,7 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2339
2472
|
try {
|
|
2340
2473
|
const content = generator.generate();
|
|
2341
2474
|
const parsed = JSON.parse(content);
|
|
2342
|
-
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("codexcli") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
2475
|
+
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("codexcli") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo") || generator.tool.includes("windsurf")) {
|
|
2343
2476
|
if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
|
|
2344
2477
|
results.push({
|
|
2345
2478
|
tool: generator.tool,
|
|
@@ -2451,12 +2584,12 @@ async function generateCommand(options = {}) {
|
|
|
2451
2584
|
for (const tool of targetTools) {
|
|
2452
2585
|
switch (tool) {
|
|
2453
2586
|
case "augmentcode":
|
|
2454
|
-
deleteTasks.push(removeDirectory(
|
|
2455
|
-
deleteTasks.push(removeDirectory(
|
|
2587
|
+
deleteTasks.push(removeDirectory(join11(".augment", "rules")));
|
|
2588
|
+
deleteTasks.push(removeDirectory(join11(".augment", "ignore")));
|
|
2456
2589
|
break;
|
|
2457
2590
|
case "augmentcode-legacy":
|
|
2458
2591
|
deleteTasks.push(removeClaudeGeneratedFiles());
|
|
2459
|
-
deleteTasks.push(removeDirectory(
|
|
2592
|
+
deleteTasks.push(removeDirectory(join11(".augment", "ignore")));
|
|
2460
2593
|
break;
|
|
2461
2594
|
case "copilot":
|
|
2462
2595
|
deleteTasks.push(removeDirectory(config.outputPaths.copilot));
|
|
@@ -2479,6 +2612,9 @@ async function generateCommand(options = {}) {
|
|
|
2479
2612
|
case "kiro":
|
|
2480
2613
|
deleteTasks.push(removeDirectory(config.outputPaths.kiro));
|
|
2481
2614
|
break;
|
|
2615
|
+
case "windsurf":
|
|
2616
|
+
deleteTasks.push(removeDirectory(config.outputPaths.windsurf));
|
|
2617
|
+
break;
|
|
2482
2618
|
}
|
|
2483
2619
|
}
|
|
2484
2620
|
await Promise.all(deleteTasks);
|
|
@@ -2551,9 +2687,9 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
2551
2687
|
|
|
2552
2688
|
// src/cli/commands/gitignore.ts
|
|
2553
2689
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
2554
|
-
import { join as
|
|
2690
|
+
import { join as join12 } from "path";
|
|
2555
2691
|
var gitignoreCommand = async () => {
|
|
2556
|
-
const gitignorePath =
|
|
2692
|
+
const gitignorePath = join12(process.cwd(), ".gitignore");
|
|
2557
2693
|
const rulesFilesToIgnore = [
|
|
2558
2694
|
"# Generated by rulesync - AI tool configuration files",
|
|
2559
2695
|
"**/.github/copilot-instructions.md",
|
|
@@ -2617,11 +2753,11 @@ ${linesToAdd.join("\n")}
|
|
|
2617
2753
|
};
|
|
2618
2754
|
|
|
2619
2755
|
// src/core/importer.ts
|
|
2620
|
-
import { join as
|
|
2621
|
-
import
|
|
2756
|
+
import { join as join19 } from "path";
|
|
2757
|
+
import matter6 from "gray-matter";
|
|
2622
2758
|
|
|
2623
2759
|
// src/parsers/augmentcode.ts
|
|
2624
|
-
import { basename as basename2, join as
|
|
2760
|
+
import { basename as basename2, join as join13 } from "path";
|
|
2625
2761
|
import matter2 from "gray-matter";
|
|
2626
2762
|
|
|
2627
2763
|
// src/utils/parser-helpers.ts
|
|
@@ -2670,7 +2806,7 @@ async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
|
2670
2806
|
async function parseUnifiedAugmentcode(baseDir, config) {
|
|
2671
2807
|
const result = createParseResult();
|
|
2672
2808
|
if (config.rulesDir) {
|
|
2673
|
-
const rulesDir =
|
|
2809
|
+
const rulesDir = join13(baseDir, config.rulesDir);
|
|
2674
2810
|
if (await fileExists(rulesDir)) {
|
|
2675
2811
|
const rulesResult = await parseAugmentRules(rulesDir, config);
|
|
2676
2812
|
addRules(result, rulesResult.rules);
|
|
@@ -2683,7 +2819,7 @@ async function parseUnifiedAugmentcode(baseDir, config) {
|
|
|
2683
2819
|
}
|
|
2684
2820
|
}
|
|
2685
2821
|
if (config.legacyFilePath) {
|
|
2686
|
-
const legacyPath =
|
|
2822
|
+
const legacyPath = join13(baseDir, config.legacyFilePath);
|
|
2687
2823
|
if (await fileExists(legacyPath)) {
|
|
2688
2824
|
const legacyResult = await parseAugmentGuidelines(legacyPath, config);
|
|
2689
2825
|
if (legacyResult.rule) {
|
|
@@ -2707,7 +2843,7 @@ async function parseAugmentRules(rulesDir, config) {
|
|
|
2707
2843
|
const files = await readdir2(rulesDir);
|
|
2708
2844
|
for (const file of files) {
|
|
2709
2845
|
if (file.endsWith(".md") || file.endsWith(".mdc")) {
|
|
2710
|
-
const filePath =
|
|
2846
|
+
const filePath = join13(rulesDir, file);
|
|
2711
2847
|
try {
|
|
2712
2848
|
const rawContent = await readFileContent(filePath);
|
|
2713
2849
|
const parsed = matter2(rawContent);
|
|
@@ -2774,7 +2910,7 @@ async function parseAugmentGuidelines(guidelinesPath, config) {
|
|
|
2774
2910
|
}
|
|
2775
2911
|
|
|
2776
2912
|
// src/parsers/shared-helpers.ts
|
|
2777
|
-
import { basename as basename3, join as
|
|
2913
|
+
import { basename as basename3, join as join14 } from "path";
|
|
2778
2914
|
import matter3 from "gray-matter";
|
|
2779
2915
|
async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
2780
2916
|
const errors = [];
|
|
@@ -2830,7 +2966,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
2830
2966
|
const files = await readdir2(dirPath);
|
|
2831
2967
|
for (const file of files) {
|
|
2832
2968
|
if (file.endsWith(dirConfig.filePattern)) {
|
|
2833
|
-
const filePath =
|
|
2969
|
+
const filePath = join14(dirPath, file);
|
|
2834
2970
|
const fileResult = await safeAsyncOperation(async () => {
|
|
2835
2971
|
const rawContent = await readFileContent(filePath);
|
|
2836
2972
|
let content;
|
|
@@ -2968,7 +3104,7 @@ async function parseMemoryFiles(memoryDir, config) {
|
|
|
2968
3104
|
const files = await readdir2(memoryDir);
|
|
2969
3105
|
for (const file of files) {
|
|
2970
3106
|
if (file.endsWith(".md")) {
|
|
2971
|
-
const filePath =
|
|
3107
|
+
const filePath = join14(memoryDir, file);
|
|
2972
3108
|
const content = await readFileContent(filePath);
|
|
2973
3109
|
if (content.trim()) {
|
|
2974
3110
|
const filename = basename3(file, ".md");
|
|
@@ -3063,7 +3199,7 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
3063
3199
|
}
|
|
3064
3200
|
|
|
3065
3201
|
// src/parsers/codexcli.ts
|
|
3066
|
-
import { join as
|
|
3202
|
+
import { join as join15 } from "path";
|
|
3067
3203
|
|
|
3068
3204
|
// src/parsers/copilot.ts
|
|
3069
3205
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
@@ -3086,7 +3222,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
3086
3222
|
}
|
|
3087
3223
|
|
|
3088
3224
|
// src/parsers/cursor.ts
|
|
3089
|
-
import { basename as basename4, join as
|
|
3225
|
+
import { basename as basename4, join as join16 } from "path";
|
|
3090
3226
|
import matter4 from "gray-matter";
|
|
3091
3227
|
import { DEFAULT_SCHEMA, FAILSAFE_SCHEMA, load } from "js-yaml";
|
|
3092
3228
|
import { z as z6 } from "zod/mini";
|
|
@@ -3211,7 +3347,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3211
3347
|
const rules = [];
|
|
3212
3348
|
let ignorePatterns;
|
|
3213
3349
|
let mcpServers;
|
|
3214
|
-
const cursorFilePath =
|
|
3350
|
+
const cursorFilePath = join16(baseDir, ".cursorrules");
|
|
3215
3351
|
if (await fileExists(cursorFilePath)) {
|
|
3216
3352
|
try {
|
|
3217
3353
|
const rawContent = await readFileContent(cursorFilePath);
|
|
@@ -3232,14 +3368,14 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3232
3368
|
errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
|
|
3233
3369
|
}
|
|
3234
3370
|
}
|
|
3235
|
-
const cursorRulesDir =
|
|
3371
|
+
const cursorRulesDir = join16(baseDir, ".cursor", "rules");
|
|
3236
3372
|
if (await fileExists(cursorRulesDir)) {
|
|
3237
3373
|
try {
|
|
3238
3374
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
3239
3375
|
const files = await readdir2(cursorRulesDir);
|
|
3240
3376
|
for (const file of files) {
|
|
3241
3377
|
if (file.endsWith(".mdc")) {
|
|
3242
|
-
const filePath =
|
|
3378
|
+
const filePath = join16(cursorRulesDir, file);
|
|
3243
3379
|
try {
|
|
3244
3380
|
const rawContent = await readFileContent(filePath);
|
|
3245
3381
|
const parsed = matter4(rawContent, customMatterOptions);
|
|
@@ -3268,7 +3404,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3268
3404
|
if (rules.length === 0) {
|
|
3269
3405
|
errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
|
|
3270
3406
|
}
|
|
3271
|
-
const cursorIgnorePath =
|
|
3407
|
+
const cursorIgnorePath = join16(baseDir, ".cursorignore");
|
|
3272
3408
|
if (await fileExists(cursorIgnorePath)) {
|
|
3273
3409
|
try {
|
|
3274
3410
|
const content = await readFileContent(cursorIgnorePath);
|
|
@@ -3281,7 +3417,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3281
3417
|
errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
|
|
3282
3418
|
}
|
|
3283
3419
|
}
|
|
3284
|
-
const cursorMcpPath =
|
|
3420
|
+
const cursorMcpPath = join16(baseDir, ".cursor", "mcp.json");
|
|
3285
3421
|
if (await fileExists(cursorMcpPath)) {
|
|
3286
3422
|
try {
|
|
3287
3423
|
const content = await readFileContent(cursorMcpPath);
|
|
@@ -3330,11 +3466,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
3330
3466
|
}
|
|
3331
3467
|
|
|
3332
3468
|
// src/parsers/junie.ts
|
|
3333
|
-
import { join as
|
|
3469
|
+
import { join as join17 } from "path";
|
|
3334
3470
|
async function parseJunieConfiguration(baseDir = process.cwd()) {
|
|
3335
3471
|
const errors = [];
|
|
3336
3472
|
const rules = [];
|
|
3337
|
-
const guidelinesPath =
|
|
3473
|
+
const guidelinesPath = join17(baseDir, ".junie", "guidelines.md");
|
|
3338
3474
|
if (!await fileExists(guidelinesPath)) {
|
|
3339
3475
|
errors.push(".junie/guidelines.md file not found");
|
|
3340
3476
|
return { rules, errors };
|
|
@@ -3385,6 +3521,11 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
|
3385
3521
|
});
|
|
3386
3522
|
}
|
|
3387
3523
|
|
|
3524
|
+
// src/parsers/windsurf.ts
|
|
3525
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
3526
|
+
import { join as join18 } from "path";
|
|
3527
|
+
import matter5 from "gray-matter";
|
|
3528
|
+
|
|
3388
3529
|
// src/core/importer.ts
|
|
3389
3530
|
async function importConfiguration(options) {
|
|
3390
3531
|
const { tool, baseDir = process.cwd(), rulesDir = ".rulesync", verbose = false } = options;
|
|
@@ -3469,7 +3610,7 @@ async function importConfiguration(options) {
|
|
|
3469
3610
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
3470
3611
|
return { success: false, rulesCreated: 0, errors };
|
|
3471
3612
|
}
|
|
3472
|
-
const rulesDirPath =
|
|
3613
|
+
const rulesDirPath = join19(baseDir, rulesDir);
|
|
3473
3614
|
try {
|
|
3474
3615
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
3475
3616
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -3483,7 +3624,7 @@ async function importConfiguration(options) {
|
|
|
3483
3624
|
try {
|
|
3484
3625
|
const baseFilename = rule.filename;
|
|
3485
3626
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
3486
|
-
const filePath =
|
|
3627
|
+
const filePath = join19(rulesDirPath, `${filename}.md`);
|
|
3487
3628
|
const content = generateRuleFileContent(rule);
|
|
3488
3629
|
await writeFileContent(filePath, content);
|
|
3489
3630
|
rulesCreated++;
|
|
@@ -3498,7 +3639,7 @@ async function importConfiguration(options) {
|
|
|
3498
3639
|
let ignoreFileCreated = false;
|
|
3499
3640
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
3500
3641
|
try {
|
|
3501
|
-
const rulesyncignorePath =
|
|
3642
|
+
const rulesyncignorePath = join19(baseDir, ".rulesyncignore");
|
|
3502
3643
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
3503
3644
|
`;
|
|
3504
3645
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -3514,7 +3655,7 @@ async function importConfiguration(options) {
|
|
|
3514
3655
|
let mcpFileCreated = false;
|
|
3515
3656
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
3516
3657
|
try {
|
|
3517
|
-
const mcpPath =
|
|
3658
|
+
const mcpPath = join19(baseDir, rulesDir, ".mcp.json");
|
|
3518
3659
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
3519
3660
|
`;
|
|
3520
3661
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -3536,13 +3677,13 @@ async function importConfiguration(options) {
|
|
|
3536
3677
|
};
|
|
3537
3678
|
}
|
|
3538
3679
|
function generateRuleFileContent(rule) {
|
|
3539
|
-
const frontmatter =
|
|
3680
|
+
const frontmatter = matter6.stringify("", rule.frontmatter);
|
|
3540
3681
|
return frontmatter + rule.content;
|
|
3541
3682
|
}
|
|
3542
3683
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
3543
3684
|
let filename = baseFilename;
|
|
3544
3685
|
let counter = 1;
|
|
3545
|
-
while (await fileExists(
|
|
3686
|
+
while (await fileExists(join19(rulesDir, `${filename}.md`))) {
|
|
3546
3687
|
filename = `${baseFilename}-${counter}`;
|
|
3547
3688
|
counter++;
|
|
3548
3689
|
}
|
|
@@ -3609,7 +3750,7 @@ async function importCommand(options = {}) {
|
|
|
3609
3750
|
}
|
|
3610
3751
|
|
|
3611
3752
|
// src/cli/commands/init.ts
|
|
3612
|
-
import { join as
|
|
3753
|
+
import { join as join20 } from "path";
|
|
3613
3754
|
async function initCommand() {
|
|
3614
3755
|
const aiRulesDir = ".rulesync";
|
|
3615
3756
|
console.log("Initializing rulesync...");
|
|
@@ -3656,7 +3797,7 @@ globs: ["**/*"]
|
|
|
3656
3797
|
- Follow single responsibility principle
|
|
3657
3798
|
`
|
|
3658
3799
|
};
|
|
3659
|
-
const filepath =
|
|
3800
|
+
const filepath = join20(aiRulesDir, sampleFile.filename);
|
|
3660
3801
|
if (!await fileExists(filepath)) {
|
|
3661
3802
|
await writeFileContent(filepath, sampleFile.content);
|
|
3662
3803
|
console.log(`Created ${filepath}`);
|
|
@@ -3800,7 +3941,7 @@ async function watchCommand() {
|
|
|
3800
3941
|
|
|
3801
3942
|
// src/cli/index.ts
|
|
3802
3943
|
var program = new Command();
|
|
3803
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
3944
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.56.0");
|
|
3804
3945
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
3805
3946
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
3806
3947
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|