rulesync 0.55.0 → 0.57.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 +117 -18
- 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 +553 -323
- package/dist/index.js +325 -168
- 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()),
|
|
@@ -222,11 +227,13 @@ var RulesyncMcpConfigSchema = z4.object({
|
|
|
222
227
|
// src/types/rules.ts
|
|
223
228
|
import { z as z5 } from "zod/mini";
|
|
224
229
|
var RuleFrontmatterSchema = z5.object({
|
|
225
|
-
root: z5.boolean(),
|
|
226
|
-
targets: RulesyncTargetsSchema,
|
|
227
|
-
description: z5.string(),
|
|
228
|
-
globs: z5.array(z5.string()),
|
|
230
|
+
root: z5.optional(z5.boolean()),
|
|
231
|
+
targets: z5.optional(RulesyncTargetsSchema),
|
|
232
|
+
description: z5.optional(z5.string()),
|
|
233
|
+
globs: z5.optional(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;
|
|
@@ -2165,7 +2293,23 @@ async function parseRuleFile(filepath) {
|
|
|
2165
2293
|
const content = await readFileContent(filepath);
|
|
2166
2294
|
const parsed = matter(content);
|
|
2167
2295
|
try {
|
|
2168
|
-
const
|
|
2296
|
+
const validatedData = RuleFrontmatterSchema.parse(parsed.data);
|
|
2297
|
+
const frontmatter = {
|
|
2298
|
+
root: validatedData.root ?? false,
|
|
2299
|
+
targets: validatedData.targets ?? ["*"],
|
|
2300
|
+
description: validatedData.description ?? "",
|
|
2301
|
+
globs: validatedData.globs ?? [],
|
|
2302
|
+
...validatedData.cursorRuleType !== void 0 && {
|
|
2303
|
+
cursorRuleType: validatedData.cursorRuleType
|
|
2304
|
+
},
|
|
2305
|
+
...validatedData.windsurfActivationMode !== void 0 && {
|
|
2306
|
+
windsurfActivationMode: validatedData.windsurfActivationMode
|
|
2307
|
+
},
|
|
2308
|
+
...validatedData.windsurfOutputFormat !== void 0 && {
|
|
2309
|
+
windsurfOutputFormat: validatedData.windsurfOutputFormat
|
|
2310
|
+
},
|
|
2311
|
+
...validatedData.tags !== void 0 && { tags: validatedData.tags }
|
|
2312
|
+
};
|
|
2169
2313
|
const filename = basename(filepath, ".md");
|
|
2170
2314
|
return {
|
|
2171
2315
|
frontmatter,
|
|
@@ -2323,6 +2467,11 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2323
2467
|
tool: "roo-project",
|
|
2324
2468
|
path: path4.join(targetRoot, ".roo", "mcp.json"),
|
|
2325
2469
|
generate: () => generateRooMcp(config)
|
|
2470
|
+
},
|
|
2471
|
+
{
|
|
2472
|
+
tool: "windsurf-project",
|
|
2473
|
+
path: path4.join(targetRoot, "mcp_config.json"),
|
|
2474
|
+
generate: () => generateWindsurfMcp(config)
|
|
2326
2475
|
}
|
|
2327
2476
|
];
|
|
2328
2477
|
const filteredGenerators = targetTools ? generators.filter((g) => {
|
|
@@ -2339,7 +2488,7 @@ async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
|
2339
2488
|
try {
|
|
2340
2489
|
const content = generator.generate();
|
|
2341
2490
|
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")) {
|
|
2491
|
+
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
2492
|
if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
|
|
2344
2493
|
results.push({
|
|
2345
2494
|
tool: generator.tool,
|
|
@@ -2451,12 +2600,12 @@ async function generateCommand(options = {}) {
|
|
|
2451
2600
|
for (const tool of targetTools) {
|
|
2452
2601
|
switch (tool) {
|
|
2453
2602
|
case "augmentcode":
|
|
2454
|
-
deleteTasks.push(removeDirectory(
|
|
2455
|
-
deleteTasks.push(removeDirectory(
|
|
2603
|
+
deleteTasks.push(removeDirectory(join11(".augment", "rules")));
|
|
2604
|
+
deleteTasks.push(removeDirectory(join11(".augment", "ignore")));
|
|
2456
2605
|
break;
|
|
2457
2606
|
case "augmentcode-legacy":
|
|
2458
2607
|
deleteTasks.push(removeClaudeGeneratedFiles());
|
|
2459
|
-
deleteTasks.push(removeDirectory(
|
|
2608
|
+
deleteTasks.push(removeDirectory(join11(".augment", "ignore")));
|
|
2460
2609
|
break;
|
|
2461
2610
|
case "copilot":
|
|
2462
2611
|
deleteTasks.push(removeDirectory(config.outputPaths.copilot));
|
|
@@ -2479,6 +2628,9 @@ async function generateCommand(options = {}) {
|
|
|
2479
2628
|
case "kiro":
|
|
2480
2629
|
deleteTasks.push(removeDirectory(config.outputPaths.kiro));
|
|
2481
2630
|
break;
|
|
2631
|
+
case "windsurf":
|
|
2632
|
+
deleteTasks.push(removeDirectory(config.outputPaths.windsurf));
|
|
2633
|
+
break;
|
|
2482
2634
|
}
|
|
2483
2635
|
}
|
|
2484
2636
|
await Promise.all(deleteTasks);
|
|
@@ -2551,9 +2703,9 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
2551
2703
|
|
|
2552
2704
|
// src/cli/commands/gitignore.ts
|
|
2553
2705
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
2554
|
-
import { join as
|
|
2706
|
+
import { join as join12 } from "path";
|
|
2555
2707
|
var gitignoreCommand = async () => {
|
|
2556
|
-
const gitignorePath =
|
|
2708
|
+
const gitignorePath = join12(process.cwd(), ".gitignore");
|
|
2557
2709
|
const rulesFilesToIgnore = [
|
|
2558
2710
|
"# Generated by rulesync - AI tool configuration files",
|
|
2559
2711
|
"**/.github/copilot-instructions.md",
|
|
@@ -2617,11 +2769,11 @@ ${linesToAdd.join("\n")}
|
|
|
2617
2769
|
};
|
|
2618
2770
|
|
|
2619
2771
|
// src/core/importer.ts
|
|
2620
|
-
import { join as
|
|
2621
|
-
import
|
|
2772
|
+
import { join as join19 } from "path";
|
|
2773
|
+
import matter6 from "gray-matter";
|
|
2622
2774
|
|
|
2623
2775
|
// src/parsers/augmentcode.ts
|
|
2624
|
-
import { basename as basename2, join as
|
|
2776
|
+
import { basename as basename2, join as join13 } from "path";
|
|
2625
2777
|
import matter2 from "gray-matter";
|
|
2626
2778
|
|
|
2627
2779
|
// src/utils/parser-helpers.ts
|
|
@@ -2670,7 +2822,7 @@ async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
|
|
|
2670
2822
|
async function parseUnifiedAugmentcode(baseDir, config) {
|
|
2671
2823
|
const result = createParseResult();
|
|
2672
2824
|
if (config.rulesDir) {
|
|
2673
|
-
const rulesDir =
|
|
2825
|
+
const rulesDir = join13(baseDir, config.rulesDir);
|
|
2674
2826
|
if (await fileExists(rulesDir)) {
|
|
2675
2827
|
const rulesResult = await parseAugmentRules(rulesDir, config);
|
|
2676
2828
|
addRules(result, rulesResult.rules);
|
|
@@ -2683,7 +2835,7 @@ async function parseUnifiedAugmentcode(baseDir, config) {
|
|
|
2683
2835
|
}
|
|
2684
2836
|
}
|
|
2685
2837
|
if (config.legacyFilePath) {
|
|
2686
|
-
const legacyPath =
|
|
2838
|
+
const legacyPath = join13(baseDir, config.legacyFilePath);
|
|
2687
2839
|
if (await fileExists(legacyPath)) {
|
|
2688
2840
|
const legacyResult = await parseAugmentGuidelines(legacyPath, config);
|
|
2689
2841
|
if (legacyResult.rule) {
|
|
@@ -2707,7 +2859,7 @@ async function parseAugmentRules(rulesDir, config) {
|
|
|
2707
2859
|
const files = await readdir2(rulesDir);
|
|
2708
2860
|
for (const file of files) {
|
|
2709
2861
|
if (file.endsWith(".md") || file.endsWith(".mdc")) {
|
|
2710
|
-
const filePath =
|
|
2862
|
+
const filePath = join13(rulesDir, file);
|
|
2711
2863
|
try {
|
|
2712
2864
|
const rawContent = await readFileContent(filePath);
|
|
2713
2865
|
const parsed = matter2(rawContent);
|
|
@@ -2774,7 +2926,7 @@ async function parseAugmentGuidelines(guidelinesPath, config) {
|
|
|
2774
2926
|
}
|
|
2775
2927
|
|
|
2776
2928
|
// src/parsers/shared-helpers.ts
|
|
2777
|
-
import { basename as basename3, join as
|
|
2929
|
+
import { basename as basename3, join as join14 } from "path";
|
|
2778
2930
|
import matter3 from "gray-matter";
|
|
2779
2931
|
async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
2780
2932
|
const errors = [];
|
|
@@ -2830,7 +2982,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
|
|
|
2830
2982
|
const files = await readdir2(dirPath);
|
|
2831
2983
|
for (const file of files) {
|
|
2832
2984
|
if (file.endsWith(dirConfig.filePattern)) {
|
|
2833
|
-
const filePath =
|
|
2985
|
+
const filePath = join14(dirPath, file);
|
|
2834
2986
|
const fileResult = await safeAsyncOperation(async () => {
|
|
2835
2987
|
const rawContent = await readFileContent(filePath);
|
|
2836
2988
|
let content;
|
|
@@ -2968,7 +3120,7 @@ async function parseMemoryFiles(memoryDir, config) {
|
|
|
2968
3120
|
const files = await readdir2(memoryDir);
|
|
2969
3121
|
for (const file of files) {
|
|
2970
3122
|
if (file.endsWith(".md")) {
|
|
2971
|
-
const filePath =
|
|
3123
|
+
const filePath = join14(memoryDir, file);
|
|
2972
3124
|
const content = await readFileContent(filePath);
|
|
2973
3125
|
if (content.trim()) {
|
|
2974
3126
|
const filename = basename3(file, ".md");
|
|
@@ -3063,7 +3215,7 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
|
|
|
3063
3215
|
}
|
|
3064
3216
|
|
|
3065
3217
|
// src/parsers/codexcli.ts
|
|
3066
|
-
import { join as
|
|
3218
|
+
import { join as join15 } from "path";
|
|
3067
3219
|
|
|
3068
3220
|
// src/parsers/copilot.ts
|
|
3069
3221
|
async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
@@ -3086,7 +3238,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
3086
3238
|
}
|
|
3087
3239
|
|
|
3088
3240
|
// src/parsers/cursor.ts
|
|
3089
|
-
import { basename as basename4, join as
|
|
3241
|
+
import { basename as basename4, join as join16 } from "path";
|
|
3090
3242
|
import matter4 from "gray-matter";
|
|
3091
3243
|
import { DEFAULT_SCHEMA, FAILSAFE_SCHEMA, load } from "js-yaml";
|
|
3092
3244
|
import { z as z6 } from "zod/mini";
|
|
@@ -3211,7 +3363,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3211
3363
|
const rules = [];
|
|
3212
3364
|
let ignorePatterns;
|
|
3213
3365
|
let mcpServers;
|
|
3214
|
-
const cursorFilePath =
|
|
3366
|
+
const cursorFilePath = join16(baseDir, ".cursorrules");
|
|
3215
3367
|
if (await fileExists(cursorFilePath)) {
|
|
3216
3368
|
try {
|
|
3217
3369
|
const rawContent = await readFileContent(cursorFilePath);
|
|
@@ -3232,14 +3384,14 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3232
3384
|
errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
|
|
3233
3385
|
}
|
|
3234
3386
|
}
|
|
3235
|
-
const cursorRulesDir =
|
|
3387
|
+
const cursorRulesDir = join16(baseDir, ".cursor", "rules");
|
|
3236
3388
|
if (await fileExists(cursorRulesDir)) {
|
|
3237
3389
|
try {
|
|
3238
3390
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
3239
3391
|
const files = await readdir2(cursorRulesDir);
|
|
3240
3392
|
for (const file of files) {
|
|
3241
3393
|
if (file.endsWith(".mdc")) {
|
|
3242
|
-
const filePath =
|
|
3394
|
+
const filePath = join16(cursorRulesDir, file);
|
|
3243
3395
|
try {
|
|
3244
3396
|
const rawContent = await readFileContent(filePath);
|
|
3245
3397
|
const parsed = matter4(rawContent, customMatterOptions);
|
|
@@ -3268,7 +3420,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3268
3420
|
if (rules.length === 0) {
|
|
3269
3421
|
errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
|
|
3270
3422
|
}
|
|
3271
|
-
const cursorIgnorePath =
|
|
3423
|
+
const cursorIgnorePath = join16(baseDir, ".cursorignore");
|
|
3272
3424
|
if (await fileExists(cursorIgnorePath)) {
|
|
3273
3425
|
try {
|
|
3274
3426
|
const content = await readFileContent(cursorIgnorePath);
|
|
@@ -3281,7 +3433,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
|
|
|
3281
3433
|
errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
|
|
3282
3434
|
}
|
|
3283
3435
|
}
|
|
3284
|
-
const cursorMcpPath =
|
|
3436
|
+
const cursorMcpPath = join16(baseDir, ".cursor", "mcp.json");
|
|
3285
3437
|
if (await fileExists(cursorMcpPath)) {
|
|
3286
3438
|
try {
|
|
3287
3439
|
const content = await readFileContent(cursorMcpPath);
|
|
@@ -3330,11 +3482,11 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
3330
3482
|
}
|
|
3331
3483
|
|
|
3332
3484
|
// src/parsers/junie.ts
|
|
3333
|
-
import { join as
|
|
3485
|
+
import { join as join17 } from "path";
|
|
3334
3486
|
async function parseJunieConfiguration(baseDir = process.cwd()) {
|
|
3335
3487
|
const errors = [];
|
|
3336
3488
|
const rules = [];
|
|
3337
|
-
const guidelinesPath =
|
|
3489
|
+
const guidelinesPath = join17(baseDir, ".junie", "guidelines.md");
|
|
3338
3490
|
if (!await fileExists(guidelinesPath)) {
|
|
3339
3491
|
errors.push(".junie/guidelines.md file not found");
|
|
3340
3492
|
return { rules, errors };
|
|
@@ -3385,6 +3537,11 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
|
3385
3537
|
});
|
|
3386
3538
|
}
|
|
3387
3539
|
|
|
3540
|
+
// src/parsers/windsurf.ts
|
|
3541
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
3542
|
+
import { join as join18 } from "path";
|
|
3543
|
+
import matter5 from "gray-matter";
|
|
3544
|
+
|
|
3388
3545
|
// src/core/importer.ts
|
|
3389
3546
|
async function importConfiguration(options) {
|
|
3390
3547
|
const { tool, baseDir = process.cwd(), rulesDir = ".rulesync", verbose = false } = options;
|
|
@@ -3469,7 +3626,7 @@ async function importConfiguration(options) {
|
|
|
3469
3626
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
3470
3627
|
return { success: false, rulesCreated: 0, errors };
|
|
3471
3628
|
}
|
|
3472
|
-
const rulesDirPath =
|
|
3629
|
+
const rulesDirPath = join19(baseDir, rulesDir);
|
|
3473
3630
|
try {
|
|
3474
3631
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
3475
3632
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -3483,7 +3640,7 @@ async function importConfiguration(options) {
|
|
|
3483
3640
|
try {
|
|
3484
3641
|
const baseFilename = rule.filename;
|
|
3485
3642
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
3486
|
-
const filePath =
|
|
3643
|
+
const filePath = join19(rulesDirPath, `${filename}.md`);
|
|
3487
3644
|
const content = generateRuleFileContent(rule);
|
|
3488
3645
|
await writeFileContent(filePath, content);
|
|
3489
3646
|
rulesCreated++;
|
|
@@ -3498,7 +3655,7 @@ async function importConfiguration(options) {
|
|
|
3498
3655
|
let ignoreFileCreated = false;
|
|
3499
3656
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
3500
3657
|
try {
|
|
3501
|
-
const rulesyncignorePath =
|
|
3658
|
+
const rulesyncignorePath = join19(baseDir, ".rulesyncignore");
|
|
3502
3659
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
3503
3660
|
`;
|
|
3504
3661
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -3514,7 +3671,7 @@ async function importConfiguration(options) {
|
|
|
3514
3671
|
let mcpFileCreated = false;
|
|
3515
3672
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
3516
3673
|
try {
|
|
3517
|
-
const mcpPath =
|
|
3674
|
+
const mcpPath = join19(baseDir, rulesDir, ".mcp.json");
|
|
3518
3675
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
3519
3676
|
`;
|
|
3520
3677
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -3536,13 +3693,13 @@ async function importConfiguration(options) {
|
|
|
3536
3693
|
};
|
|
3537
3694
|
}
|
|
3538
3695
|
function generateRuleFileContent(rule) {
|
|
3539
|
-
const frontmatter =
|
|
3696
|
+
const frontmatter = matter6.stringify("", rule.frontmatter);
|
|
3540
3697
|
return frontmatter + rule.content;
|
|
3541
3698
|
}
|
|
3542
3699
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
3543
3700
|
let filename = baseFilename;
|
|
3544
3701
|
let counter = 1;
|
|
3545
|
-
while (await fileExists(
|
|
3702
|
+
while (await fileExists(join19(rulesDir, `${filename}.md`))) {
|
|
3546
3703
|
filename = `${baseFilename}-${counter}`;
|
|
3547
3704
|
counter++;
|
|
3548
3705
|
}
|
|
@@ -3609,7 +3766,7 @@ async function importCommand(options = {}) {
|
|
|
3609
3766
|
}
|
|
3610
3767
|
|
|
3611
3768
|
// src/cli/commands/init.ts
|
|
3612
|
-
import { join as
|
|
3769
|
+
import { join as join20 } from "path";
|
|
3613
3770
|
async function initCommand() {
|
|
3614
3771
|
const aiRulesDir = ".rulesync";
|
|
3615
3772
|
console.log("Initializing rulesync...");
|
|
@@ -3656,7 +3813,7 @@ globs: ["**/*"]
|
|
|
3656
3813
|
- Follow single responsibility principle
|
|
3657
3814
|
`
|
|
3658
3815
|
};
|
|
3659
|
-
const filepath =
|
|
3816
|
+
const filepath = join20(aiRulesDir, sampleFile.filename);
|
|
3660
3817
|
if (!await fileExists(filepath)) {
|
|
3661
3818
|
await writeFileContent(filepath, sampleFile.content);
|
|
3662
3819
|
console.log(`Created ${filepath}`);
|
|
@@ -3800,7 +3957,7 @@ async function watchCommand() {
|
|
|
3800
3957
|
|
|
3801
3958
|
// src/cli/index.ts
|
|
3802
3959
|
var program = new Command();
|
|
3803
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
3960
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.57.0");
|
|
3804
3961
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
3805
3962
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
3806
3963
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|