rulesync 0.49.0 → 0.52.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 +3 -2
- package/README.md +90 -2
- package/dist/{augmentcode-KTXT5GMO.js → augmentcode-ICLQ2NEZ.js} +2 -2
- package/dist/{chunk-MCADLVGY.js → chunk-FFW6TGCM.js} +1 -1
- package/dist/chunk-FNL2KPM3.js +63 -0
- package/dist/chunk-HMMTSS5E.js +54 -0
- package/dist/{chunk-QNHGYRJT.js → chunk-IXCMY24P.js} +1 -1
- package/dist/{chunk-6TAURCQP.js → chunk-OPZOVKIL.js} +1 -1
- package/dist/{chunk-R5HFWJ5L.js → chunk-QUJMXHNR.js} +1 -1
- package/dist/{chunk-6MFEIYHN.js → chunk-TTHBLXOB.js} +1 -1
- package/dist/{chunk-IBJGN3JQ.js → chunk-USKQYIZ2.js} +11 -3
- package/dist/chunk-Y26DXTAT.js +90 -0
- package/dist/{chunk-G5LLOIO4.js → chunk-Y2XH4E5R.js} +1 -1
- package/dist/chunk-YPIFCGAP.js +94 -0
- package/dist/{claudecode-OE4TSKPS.js → claudecode-4XWK2WAY.js} +3 -2
- package/dist/{cline-CWLQS5CV.js → cline-MNXOHP77.js} +3 -2
- package/dist/{copilot-PVZDRAU5.js → copilot-ARYIWVJ7.js} +2 -2
- package/dist/{cursor-ZZV7AY6H.js → cursor-FCS74IAH.js} +2 -2
- package/dist/{geminicli-RSXOWFEN.js → geminicli-VOPV6DXZ.js} +2 -2
- package/dist/index.cjs +1427 -587
- package/dist/index.js +1303 -541
- package/dist/junie-A2Y2WZI4.js +9 -0
- package/dist/{kiro-YRKVCDIQ.js → kiro-MHIK4UBV.js} +2 -2
- package/dist/{roo-HCRGELWQ.js → roo-VG4IUNTE.js} +2 -2
- package/package.json +17 -16
- package/dist/chunk-XHNIEO22.js +0 -62
- package/dist/chunk-YVRWBSCK.js +0 -73
package/dist/index.cjs
CHANGED
|
@@ -27,12 +27,16 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
));
|
|
28
28
|
|
|
29
29
|
// src/types/tool-targets.ts
|
|
30
|
-
|
|
30
|
+
function isToolTarget(target) {
|
|
31
|
+
if (!target) return false;
|
|
32
|
+
return ALL_TOOL_TARGETS.some((validTarget) => validTarget === target);
|
|
33
|
+
}
|
|
34
|
+
var import_mini, ALL_TOOL_TARGETS, ToolTargetSchema, ToolTargetsSchema, WildcardTargetSchema, RulesyncTargetsSchema;
|
|
31
35
|
var init_tool_targets = __esm({
|
|
32
36
|
"src/types/tool-targets.ts"() {
|
|
33
37
|
"use strict";
|
|
34
38
|
import_mini = require("zod/mini");
|
|
35
|
-
|
|
39
|
+
ALL_TOOL_TARGETS = [
|
|
36
40
|
"augmentcode",
|
|
37
41
|
"augmentcode-legacy",
|
|
38
42
|
"copilot",
|
|
@@ -41,8 +45,10 @@ var init_tool_targets = __esm({
|
|
|
41
45
|
"claudecode",
|
|
42
46
|
"roo",
|
|
43
47
|
"geminicli",
|
|
44
|
-
"kiro"
|
|
45
|
-
|
|
48
|
+
"kiro",
|
|
49
|
+
"junie"
|
|
50
|
+
];
|
|
51
|
+
ToolTargetSchema = import_mini.z.enum(ALL_TOOL_TARGETS);
|
|
46
52
|
ToolTargetsSchema = import_mini.z.array(ToolTargetSchema);
|
|
47
53
|
WildcardTargetSchema = import_mini.z.tuple([import_mini.z.literal("*")]);
|
|
48
54
|
RulesyncTargetsSchema = import_mini.z.union([ToolTargetsSchema, WildcardTargetSchema]);
|
|
@@ -130,84 +136,108 @@ var init_augmentcode = __esm({
|
|
|
130
136
|
}
|
|
131
137
|
});
|
|
132
138
|
|
|
139
|
+
// src/generators/mcp/shared-factory.ts
|
|
140
|
+
function generateMcpConfig(config, toolConfig) {
|
|
141
|
+
const servers = {};
|
|
142
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
143
|
+
if (!shouldIncludeServer(server, toolConfig.target)) continue;
|
|
144
|
+
servers[serverName] = toolConfig.serverTransform(server, serverName);
|
|
145
|
+
}
|
|
146
|
+
const finalConfig = toolConfig.configWrapper(servers);
|
|
147
|
+
return JSON.stringify(finalConfig, null, 2);
|
|
148
|
+
}
|
|
149
|
+
var configWrappers;
|
|
150
|
+
var init_shared_factory = __esm({
|
|
151
|
+
"src/generators/mcp/shared-factory.ts"() {
|
|
152
|
+
"use strict";
|
|
153
|
+
init_mcp_helpers();
|
|
154
|
+
configWrappers = {
|
|
155
|
+
/**
|
|
156
|
+
* Standard mcpServers wrapper
|
|
157
|
+
*/
|
|
158
|
+
mcpServers: (servers) => ({
|
|
159
|
+
mcpServers: servers
|
|
160
|
+
}),
|
|
161
|
+
/**
|
|
162
|
+
* Servers-only wrapper (for tools that use "servers" instead of "mcpServers")
|
|
163
|
+
*/
|
|
164
|
+
servers: (servers) => ({
|
|
165
|
+
servers
|
|
166
|
+
})
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
133
171
|
// src/generators/mcp/claudecode.ts
|
|
134
172
|
function generateClaudeMcp(config) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
173
|
+
return generateMcpConfig(config, {
|
|
174
|
+
target: "claudecode",
|
|
175
|
+
configPaths: [".claude/settings.json"],
|
|
176
|
+
serverTransform: (server) => {
|
|
177
|
+
const claudeServer = {};
|
|
178
|
+
if (server.command) {
|
|
179
|
+
claudeServer.command = server.command;
|
|
180
|
+
if (server.args) claudeServer.args = server.args;
|
|
181
|
+
} else if (server.url || server.httpUrl) {
|
|
182
|
+
const url = server.httpUrl || server.url;
|
|
183
|
+
if (url) {
|
|
184
|
+
claudeServer.url = url;
|
|
185
|
+
}
|
|
186
|
+
if (server.httpUrl) {
|
|
187
|
+
claudeServer.transport = "http";
|
|
188
|
+
} else if (server.transport === "sse") {
|
|
189
|
+
claudeServer.transport = "sse";
|
|
190
|
+
}
|
|
151
191
|
}
|
|
152
|
-
if (server.
|
|
153
|
-
claudeServer.
|
|
154
|
-
} else if (server.transport === "sse") {
|
|
155
|
-
claudeServer.transport = "sse";
|
|
192
|
+
if (server.env) {
|
|
193
|
+
claudeServer.env = server.env;
|
|
156
194
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (claudeSettings.mcpServers) {
|
|
162
|
-
claudeSettings.mcpServers[serverName] = claudeServer;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return JSON.stringify(claudeSettings, null, 2);
|
|
195
|
+
return claudeServer;
|
|
196
|
+
},
|
|
197
|
+
configWrapper: configWrappers.mcpServers
|
|
198
|
+
});
|
|
166
199
|
}
|
|
167
200
|
var init_claudecode = __esm({
|
|
168
201
|
"src/generators/mcp/claudecode.ts"() {
|
|
169
202
|
"use strict";
|
|
170
|
-
|
|
203
|
+
init_shared_factory();
|
|
171
204
|
}
|
|
172
205
|
});
|
|
173
206
|
|
|
174
207
|
// src/generators/mcp/cline.ts
|
|
175
208
|
function generateClineMcp(config) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (server.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
clineConfig.mcpServers[serverName] = clineServer;
|
|
204
|
-
}
|
|
205
|
-
return JSON.stringify(clineConfig, null, 2);
|
|
209
|
+
return generateMcpConfig(config, {
|
|
210
|
+
target: "cline",
|
|
211
|
+
configPaths: [".cline/mcp.json"],
|
|
212
|
+
serverTransform: (server) => {
|
|
213
|
+
const clineServer = {};
|
|
214
|
+
if (server.command) {
|
|
215
|
+
clineServer.command = server.command;
|
|
216
|
+
if (server.args) clineServer.args = server.args;
|
|
217
|
+
} else if (server.url) {
|
|
218
|
+
clineServer.url = server.url;
|
|
219
|
+
}
|
|
220
|
+
if (server.env) {
|
|
221
|
+
clineServer.env = server.env;
|
|
222
|
+
}
|
|
223
|
+
if (server.disabled !== void 0) {
|
|
224
|
+
clineServer.disabled = server.disabled;
|
|
225
|
+
}
|
|
226
|
+
if (server.alwaysAllow) {
|
|
227
|
+
clineServer.alwaysAllow = server.alwaysAllow;
|
|
228
|
+
}
|
|
229
|
+
if (server.networkTimeout !== void 0) {
|
|
230
|
+
clineServer.networkTimeout = server.networkTimeout;
|
|
231
|
+
}
|
|
232
|
+
return clineServer;
|
|
233
|
+
},
|
|
234
|
+
configWrapper: configWrappers.mcpServers
|
|
235
|
+
});
|
|
206
236
|
}
|
|
207
237
|
var init_cline = __esm({
|
|
208
238
|
"src/generators/mcp/cline.ts"() {
|
|
209
239
|
"use strict";
|
|
210
|
-
|
|
240
|
+
init_shared_factory();
|
|
211
241
|
}
|
|
212
242
|
});
|
|
213
243
|
|
|
@@ -354,6 +384,58 @@ var init_geminicli = __esm({
|
|
|
354
384
|
}
|
|
355
385
|
});
|
|
356
386
|
|
|
387
|
+
// src/generators/mcp/junie.ts
|
|
388
|
+
function generateJunieMcp(config) {
|
|
389
|
+
const junieConfig = {
|
|
390
|
+
mcpServers: {}
|
|
391
|
+
};
|
|
392
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
393
|
+
if (!shouldIncludeServer(server, "junie")) continue;
|
|
394
|
+
const junieServer = {
|
|
395
|
+
name: serverName
|
|
396
|
+
};
|
|
397
|
+
if (server.command) {
|
|
398
|
+
junieServer.command = server.command;
|
|
399
|
+
if (server.args) junieServer.args = server.args;
|
|
400
|
+
} else if (server.url || server.httpUrl) {
|
|
401
|
+
if (server.httpUrl) {
|
|
402
|
+
junieServer.httpUrl = server.httpUrl;
|
|
403
|
+
} else if (server.url) {
|
|
404
|
+
junieServer.url = server.url;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (server.env) {
|
|
408
|
+
junieServer.env = server.env;
|
|
409
|
+
}
|
|
410
|
+
if (server.cwd) {
|
|
411
|
+
junieServer.workingDirectory = server.cwd;
|
|
412
|
+
}
|
|
413
|
+
if (server.timeout !== void 0) {
|
|
414
|
+
junieServer.timeout = server.timeout;
|
|
415
|
+
}
|
|
416
|
+
if (server.trust !== void 0) {
|
|
417
|
+
junieServer.trust = server.trust;
|
|
418
|
+
}
|
|
419
|
+
if (server.transport) {
|
|
420
|
+
if (String(server.transport) === "streamable-http") {
|
|
421
|
+
junieServer.transport = "http";
|
|
422
|
+
} else if (server.transport === "stdio" || server.transport === "http" || server.transport === "sse") {
|
|
423
|
+
junieServer.transport = server.transport;
|
|
424
|
+
}
|
|
425
|
+
} else if (server.command) {
|
|
426
|
+
junieServer.transport = "stdio";
|
|
427
|
+
}
|
|
428
|
+
junieConfig.mcpServers[serverName] = junieServer;
|
|
429
|
+
}
|
|
430
|
+
return JSON.stringify(junieConfig, null, 2);
|
|
431
|
+
}
|
|
432
|
+
var init_junie = __esm({
|
|
433
|
+
"src/generators/mcp/junie.ts"() {
|
|
434
|
+
"use strict";
|
|
435
|
+
init_mcp_helpers();
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
|
|
357
439
|
// src/generators/mcp/kiro.ts
|
|
358
440
|
function generateKiroMcp(config) {
|
|
359
441
|
const kiroConfig = {
|
|
@@ -478,19 +560,11 @@ function getDefaultConfig() {
|
|
|
478
560
|
claudecode: ".",
|
|
479
561
|
roo: ".roo/rules",
|
|
480
562
|
geminicli: ".gemini/memories",
|
|
481
|
-
kiro: ".kiro/steering"
|
|
563
|
+
kiro: ".kiro/steering",
|
|
564
|
+
junie: "."
|
|
482
565
|
},
|
|
483
566
|
watchEnabled: false,
|
|
484
|
-
defaultTargets:
|
|
485
|
-
"augmentcode",
|
|
486
|
-
"copilot",
|
|
487
|
-
"cursor",
|
|
488
|
-
"cline",
|
|
489
|
-
"claudecode",
|
|
490
|
-
"roo",
|
|
491
|
-
"geminicli",
|
|
492
|
-
"kiro"
|
|
493
|
-
]
|
|
567
|
+
defaultTargets: ALL_TOOL_TARGETS.filter((tool) => tool !== "augmentcode-legacy")
|
|
494
568
|
};
|
|
495
569
|
}
|
|
496
570
|
function resolveTargets(targets, config) {
|
|
@@ -537,267 +611,643 @@ async function addCommand(filename) {
|
|
|
537
611
|
}
|
|
538
612
|
}
|
|
539
613
|
|
|
540
|
-
// src/
|
|
541
|
-
var
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
)
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
)
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
)
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
614
|
+
// src/cli/commands/config.ts
|
|
615
|
+
var import_node_fs = require("fs");
|
|
616
|
+
var import_node_path2 = __toESM(require("path"), 1);
|
|
617
|
+
|
|
618
|
+
// src/types/claudecode.ts
|
|
619
|
+
var import_mini2 = require("zod/mini");
|
|
620
|
+
var ClaudeSettingsSchema = import_mini2.z.looseObject({
|
|
621
|
+
permissions: import_mini2.z._default(
|
|
622
|
+
import_mini2.z.looseObject({
|
|
623
|
+
deny: import_mini2.z._default(import_mini2.z.array(import_mini2.z.string()), [])
|
|
624
|
+
}),
|
|
625
|
+
{ deny: [] }
|
|
626
|
+
)
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
// src/types/config.ts
|
|
630
|
+
var import_mini3 = require("zod/mini");
|
|
631
|
+
init_tool_targets();
|
|
632
|
+
var ConfigSchema = import_mini3.z.object({
|
|
633
|
+
aiRulesDir: import_mini3.z.string(),
|
|
634
|
+
outputPaths: import_mini3.z.record(ToolTargetSchema, import_mini3.z.string()),
|
|
635
|
+
watchEnabled: import_mini3.z.boolean(),
|
|
636
|
+
defaultTargets: ToolTargetsSchema
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
// src/types/config-options.ts
|
|
640
|
+
var import_mini4 = require("zod/mini");
|
|
641
|
+
init_tool_targets();
|
|
642
|
+
var OutputPathsSchema = import_mini4.z.object({
|
|
643
|
+
augmentcode: import_mini4.z.optional(import_mini4.z.string()),
|
|
644
|
+
"augmentcode-legacy": import_mini4.z.optional(import_mini4.z.string()),
|
|
645
|
+
copilot: import_mini4.z.optional(import_mini4.z.string()),
|
|
646
|
+
cursor: import_mini4.z.optional(import_mini4.z.string()),
|
|
647
|
+
cline: import_mini4.z.optional(import_mini4.z.string()),
|
|
648
|
+
claudecode: import_mini4.z.optional(import_mini4.z.string()),
|
|
649
|
+
roo: import_mini4.z.optional(import_mini4.z.string()),
|
|
650
|
+
geminicli: import_mini4.z.optional(import_mini4.z.string()),
|
|
651
|
+
kiro: import_mini4.z.optional(import_mini4.z.string()),
|
|
652
|
+
junie: import_mini4.z.optional(import_mini4.z.string())
|
|
653
|
+
});
|
|
654
|
+
var ConfigOptionsSchema = import_mini4.z.object({
|
|
655
|
+
aiRulesDir: import_mini4.z.optional(import_mini4.z.string()),
|
|
656
|
+
outputPaths: import_mini4.z.optional(OutputPathsSchema),
|
|
657
|
+
watchEnabled: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
658
|
+
defaultTargets: import_mini4.z.optional(ToolTargetsSchema),
|
|
659
|
+
targets: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
|
|
660
|
+
exclude: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
|
|
661
|
+
verbose: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
662
|
+
delete: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
663
|
+
baseDir: import_mini4.z.optional(import_mini4.z.union([import_mini4.z.string(), import_mini4.z.array(import_mini4.z.string())])),
|
|
664
|
+
watch: import_mini4.z.optional(
|
|
665
|
+
import_mini4.z.object({
|
|
666
|
+
enabled: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
667
|
+
interval: import_mini4.z.optional(import_mini4.z.number()),
|
|
668
|
+
ignore: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string()))
|
|
669
|
+
})
|
|
670
|
+
)
|
|
671
|
+
});
|
|
672
|
+
var MergedConfigSchema = import_mini4.z.object({
|
|
673
|
+
aiRulesDir: import_mini4.z.string(),
|
|
674
|
+
outputPaths: import_mini4.z.record(ToolTargetSchema, import_mini4.z.string()),
|
|
675
|
+
watchEnabled: import_mini4.z.boolean(),
|
|
676
|
+
defaultTargets: ToolTargetsSchema,
|
|
677
|
+
targets: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
|
|
678
|
+
exclude: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
|
|
679
|
+
verbose: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
680
|
+
delete: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
681
|
+
baseDir: import_mini4.z.optional(import_mini4.z.union([import_mini4.z.string(), import_mini4.z.array(import_mini4.z.string())])),
|
|
682
|
+
configPath: import_mini4.z.optional(import_mini4.z.string()),
|
|
683
|
+
watch: import_mini4.z.optional(
|
|
684
|
+
import_mini4.z.object({
|
|
685
|
+
enabled: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
686
|
+
interval: import_mini4.z.optional(import_mini4.z.number()),
|
|
687
|
+
ignore: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string()))
|
|
688
|
+
})
|
|
689
|
+
)
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
// src/types/mcp.ts
|
|
693
|
+
var import_mini5 = require("zod/mini");
|
|
694
|
+
init_tool_targets();
|
|
695
|
+
var McpTransportTypeSchema = import_mini5.z.enum(["stdio", "sse", "http"]);
|
|
696
|
+
var McpServerBaseSchema = import_mini5.z.object({
|
|
697
|
+
command: import_mini5.z.optional(import_mini5.z.string()),
|
|
698
|
+
args: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
699
|
+
url: import_mini5.z.optional(import_mini5.z.string()),
|
|
700
|
+
httpUrl: import_mini5.z.optional(import_mini5.z.string()),
|
|
701
|
+
env: import_mini5.z.optional(import_mini5.z.record(import_mini5.z.string(), import_mini5.z.string())),
|
|
702
|
+
disabled: import_mini5.z.optional(import_mini5.z.boolean()),
|
|
703
|
+
networkTimeout: import_mini5.z.optional(import_mini5.z.number()),
|
|
704
|
+
timeout: import_mini5.z.optional(import_mini5.z.number()),
|
|
705
|
+
trust: import_mini5.z.optional(import_mini5.z.boolean()),
|
|
706
|
+
cwd: import_mini5.z.optional(import_mini5.z.string()),
|
|
707
|
+
transport: import_mini5.z.optional(McpTransportTypeSchema),
|
|
708
|
+
type: import_mini5.z.optional(import_mini5.z.enum(["sse", "streamable-http"])),
|
|
709
|
+
alwaysAllow: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
710
|
+
tools: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
711
|
+
kiroAutoApprove: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
|
|
712
|
+
kiroAutoBlock: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string()))
|
|
713
|
+
});
|
|
714
|
+
var RulesyncMcpServerSchema = import_mini5.z.extend(McpServerBaseSchema, {
|
|
715
|
+
targets: import_mini5.z.optional(RulesyncTargetsSchema)
|
|
716
|
+
});
|
|
717
|
+
var McpConfigSchema = import_mini5.z.object({
|
|
718
|
+
mcpServers: import_mini5.z.record(import_mini5.z.string(), McpServerBaseSchema)
|
|
719
|
+
});
|
|
720
|
+
var RulesyncMcpConfigSchema = import_mini5.z.object({
|
|
721
|
+
mcpServers: import_mini5.z.record(import_mini5.z.string(), RulesyncMcpServerSchema)
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
// src/types/rules.ts
|
|
725
|
+
var import_mini6 = require("zod/mini");
|
|
726
|
+
init_tool_targets();
|
|
727
|
+
var RuleFrontmatterSchema = import_mini6.z.object({
|
|
728
|
+
root: import_mini6.z.boolean(),
|
|
729
|
+
targets: RulesyncTargetsSchema,
|
|
730
|
+
description: import_mini6.z.string(),
|
|
731
|
+
globs: import_mini6.z.array(import_mini6.z.string()),
|
|
732
|
+
cursorRuleType: import_mini6.z.optional(import_mini6.z.enum(["always", "manual", "specificFiles", "intelligently"])),
|
|
733
|
+
tags: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string()))
|
|
734
|
+
});
|
|
735
|
+
var ParsedRuleSchema = import_mini6.z.object({
|
|
736
|
+
frontmatter: RuleFrontmatterSchema,
|
|
737
|
+
content: import_mini6.z.string(),
|
|
738
|
+
filename: import_mini6.z.string(),
|
|
739
|
+
filepath: import_mini6.z.string()
|
|
740
|
+
});
|
|
741
|
+
var GeneratedOutputSchema = import_mini6.z.object({
|
|
742
|
+
tool: ToolTargetSchema,
|
|
743
|
+
filepath: import_mini6.z.string(),
|
|
744
|
+
content: import_mini6.z.string()
|
|
745
|
+
});
|
|
746
|
+
var GenerateOptionsSchema = import_mini6.z.object({
|
|
747
|
+
targetTools: import_mini6.z.optional(ToolTargetsSchema),
|
|
748
|
+
outputDir: import_mini6.z.optional(import_mini6.z.string()),
|
|
749
|
+
watch: import_mini6.z.optional(import_mini6.z.boolean())
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
// src/types/index.ts
|
|
753
|
+
init_tool_targets();
|
|
754
|
+
|
|
755
|
+
// src/utils/config-loader.ts
|
|
756
|
+
var import_c12 = require("c12");
|
|
757
|
+
var import_core = require("zod/v4/core");
|
|
758
|
+
var MODULE_NAME = "rulesync";
|
|
759
|
+
async function loadConfig(options = {}) {
|
|
760
|
+
const defaultConfig = getDefaultConfig();
|
|
761
|
+
if (options.noConfig) {
|
|
762
|
+
return {
|
|
763
|
+
config: defaultConfig,
|
|
764
|
+
isEmpty: true
|
|
765
|
+
};
|
|
653
766
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
patterns.push(glob);
|
|
682
|
-
}
|
|
767
|
+
try {
|
|
768
|
+
const loadOptions = {
|
|
769
|
+
name: MODULE_NAME,
|
|
770
|
+
cwd: options.cwd || process.cwd(),
|
|
771
|
+
rcFile: false,
|
|
772
|
+
// Disable rc file lookup
|
|
773
|
+
configFile: "rulesync",
|
|
774
|
+
// Will look for rulesync.jsonc, rulesync.ts, etc.
|
|
775
|
+
defaults: defaultConfig
|
|
776
|
+
};
|
|
777
|
+
if (options.configPath) {
|
|
778
|
+
loadOptions.configFile = options.configPath;
|
|
779
|
+
}
|
|
780
|
+
const { config, configFile } = await (0, import_c12.loadConfig)(loadOptions);
|
|
781
|
+
if (!config || Object.keys(config).length === 0) {
|
|
782
|
+
return {
|
|
783
|
+
config: defaultConfig,
|
|
784
|
+
isEmpty: true
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
try {
|
|
788
|
+
ConfigOptionsSchema.parse(config);
|
|
789
|
+
} catch (error) {
|
|
790
|
+
if (error instanceof import_core.$ZodError) {
|
|
791
|
+
const issues = error.issues.map((issue) => ` - ${issue.path.join(".")}: ${issue.message}`).join("\n");
|
|
792
|
+
throw new Error(`Invalid configuration in ${configFile}:
|
|
793
|
+
${issues}`);
|
|
683
794
|
}
|
|
795
|
+
throw error;
|
|
684
796
|
}
|
|
685
|
-
const
|
|
686
|
-
|
|
797
|
+
const processedConfig = postProcessConfig(config);
|
|
798
|
+
const result = {
|
|
799
|
+
config: processedConfig,
|
|
800
|
+
isEmpty: false
|
|
801
|
+
};
|
|
802
|
+
if (configFile) {
|
|
803
|
+
result.filepath = configFile;
|
|
804
|
+
}
|
|
805
|
+
return result;
|
|
806
|
+
} catch (error) {
|
|
807
|
+
throw new Error(
|
|
808
|
+
`Failed to load configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
809
|
+
);
|
|
687
810
|
}
|
|
688
|
-
return patterns;
|
|
689
811
|
}
|
|
690
|
-
function
|
|
691
|
-
const
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
"**/deploy/prod/**",
|
|
707
|
-
// Internal documentation
|
|
708
|
-
"**/internal-docs/**",
|
|
709
|
-
"**/proprietary/**",
|
|
710
|
-
"**/personal-notes/**",
|
|
711
|
-
"**/private/**",
|
|
712
|
-
"**/confidential/**"
|
|
713
|
-
];
|
|
714
|
-
return excludePatterns.some((pattern) => {
|
|
715
|
-
const regex = new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*"));
|
|
716
|
-
return regex.test(glob);
|
|
717
|
-
});
|
|
812
|
+
function postProcessConfig(config) {
|
|
813
|
+
const processed = { ...config };
|
|
814
|
+
if (processed.baseDir && !Array.isArray(processed.baseDir)) {
|
|
815
|
+
processed.baseDir = [processed.baseDir];
|
|
816
|
+
}
|
|
817
|
+
if (config.targets || config.exclude) {
|
|
818
|
+
const baseTargets = config.targets || processed.defaultTargets;
|
|
819
|
+
if (config.exclude && config.exclude.length > 0) {
|
|
820
|
+
processed.defaultTargets = baseTargets.filter(
|
|
821
|
+
(target) => config.exclude && !config.exclude.includes(target)
|
|
822
|
+
);
|
|
823
|
+
} else {
|
|
824
|
+
processed.defaultTargets = baseTargets;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return processed;
|
|
718
828
|
}
|
|
719
|
-
function
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
829
|
+
function generateMinimalConfig(options) {
|
|
830
|
+
if (!options || Object.keys(options).length === 0) {
|
|
831
|
+
return generateSampleConfig();
|
|
832
|
+
}
|
|
833
|
+
const lines = ["{"];
|
|
834
|
+
if (options.targets || options.exclude) {
|
|
835
|
+
lines.push(` // Available tools: ${ALL_TOOL_TARGETS.join(", ")}`);
|
|
836
|
+
}
|
|
837
|
+
if (options.targets) {
|
|
838
|
+
lines.push(` "targets": ${JSON.stringify(options.targets)}`);
|
|
839
|
+
}
|
|
840
|
+
if (options.exclude) {
|
|
841
|
+
const comma = lines.length > 1 ? "," : "";
|
|
842
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
843
|
+
lines.push(` "exclude": ${JSON.stringify(options.exclude)}`);
|
|
844
|
+
}
|
|
845
|
+
if (options.aiRulesDir) {
|
|
846
|
+
const comma = lines.length > 1 ? "," : "";
|
|
847
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
848
|
+
lines.push(` "aiRulesDir": "${options.aiRulesDir}"`);
|
|
849
|
+
}
|
|
850
|
+
if (options.outputPaths) {
|
|
851
|
+
const comma = lines.length > 1 ? "," : "";
|
|
852
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
853
|
+
lines.push(
|
|
854
|
+
` "outputPaths": ${JSON.stringify(options.outputPaths, null, 4).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n")}`
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
if (options.baseDir) {
|
|
858
|
+
const comma = lines.length > 1 ? "," : "";
|
|
859
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
860
|
+
lines.push(` "baseDir": ${JSON.stringify(options.baseDir)}`);
|
|
861
|
+
}
|
|
862
|
+
if (options.delete !== void 0) {
|
|
863
|
+
const comma = lines.length > 1 ? "," : "";
|
|
864
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
865
|
+
lines.push(` "delete": ${options.delete}`);
|
|
866
|
+
}
|
|
867
|
+
if (options.verbose !== void 0) {
|
|
868
|
+
const comma = lines.length > 1 ? "," : "";
|
|
869
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
870
|
+
lines.push(` "verbose": ${options.verbose}`);
|
|
871
|
+
}
|
|
872
|
+
if (options.watch) {
|
|
873
|
+
const comma = lines.length > 1 ? "," : "";
|
|
874
|
+
if (comma) lines[lines.length - 1] += comma;
|
|
875
|
+
lines.push(
|
|
876
|
+
` "watch": ${JSON.stringify(options.watch, null, 4).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n")}`
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
lines.push("}");
|
|
880
|
+
return lines.join("\n");
|
|
881
|
+
}
|
|
882
|
+
function generateSampleConfig(options) {
|
|
883
|
+
const targets = options?.targets || ALL_TOOL_TARGETS;
|
|
884
|
+
const excludeValue = options?.exclude ? JSON.stringify(options.exclude) : null;
|
|
885
|
+
const aiRulesDir = options?.aiRulesDir || null;
|
|
886
|
+
const baseDir = options?.baseDir || null;
|
|
887
|
+
const deleteFlag = options?.delete || false;
|
|
888
|
+
const verbose = options?.verbose !== void 0 ? options.verbose : true;
|
|
889
|
+
return `{
|
|
890
|
+
// List of tools to generate configurations for
|
|
891
|
+
// Available: ${ALL_TOOL_TARGETS.join(", ")}
|
|
892
|
+
"targets": ${JSON.stringify(targets)},
|
|
893
|
+
|
|
894
|
+
// Tools to exclude from generation (overrides targets)
|
|
895
|
+
${excludeValue ? `"exclude": ${excludeValue},` : '// "exclude": ["roo"],'}
|
|
896
|
+
${aiRulesDir ? `
|
|
897
|
+
// Directory containing AI rule files
|
|
898
|
+
"aiRulesDir": "${aiRulesDir}",` : ""}
|
|
899
|
+
|
|
900
|
+
// Custom output paths for specific tools
|
|
901
|
+
"outputPaths": {
|
|
902
|
+
"copilot": ".github/copilot-instructions.md"
|
|
903
|
+
},
|
|
904
|
+
${baseDir ? `
|
|
905
|
+
// Base directory for generation
|
|
906
|
+
"baseDir": "${baseDir}",` : `
|
|
907
|
+
// Base directory or directories for generation
|
|
908
|
+
// "baseDir": "./packages",
|
|
909
|
+
// "baseDir": ["./packages/frontend", "./packages/backend"],`}
|
|
910
|
+
|
|
911
|
+
// Delete existing files before generating
|
|
912
|
+
"delete": ${deleteFlag},
|
|
913
|
+
|
|
914
|
+
// Enable verbose output
|
|
915
|
+
"verbose": ${verbose},
|
|
916
|
+
|
|
917
|
+
// Watch configuration
|
|
918
|
+
"watch": {
|
|
919
|
+
"enabled": false,
|
|
920
|
+
"interval": 1000,
|
|
921
|
+
"ignore": ["node_modules/**", "dist/**"]
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
`;
|
|
925
|
+
}
|
|
926
|
+
function mergeWithCliOptions(config, cliOptions) {
|
|
927
|
+
const merged = { ...config };
|
|
928
|
+
if (cliOptions.verbose !== void 0) {
|
|
929
|
+
merged.verbose = cliOptions.verbose;
|
|
930
|
+
}
|
|
931
|
+
if (cliOptions.delete !== void 0) {
|
|
932
|
+
merged.delete = cliOptions.delete;
|
|
933
|
+
}
|
|
934
|
+
if (cliOptions.baseDirs && cliOptions.baseDirs.length > 0) {
|
|
935
|
+
merged.baseDir = cliOptions.baseDirs;
|
|
936
|
+
}
|
|
937
|
+
if (cliOptions.tools && cliOptions.tools.length > 0) {
|
|
938
|
+
merged.defaultTargets = cliOptions.tools;
|
|
939
|
+
merged.exclude = void 0;
|
|
940
|
+
}
|
|
941
|
+
return merged;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// src/utils/file.ts
|
|
945
|
+
var import_promises2 = require("fs/promises");
|
|
946
|
+
var import_node_path = require("path");
|
|
947
|
+
async function ensureDir(dirPath) {
|
|
948
|
+
try {
|
|
949
|
+
await (0, import_promises2.stat)(dirPath);
|
|
950
|
+
} catch {
|
|
951
|
+
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
async function readFileContent(filepath) {
|
|
955
|
+
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
956
|
+
}
|
|
957
|
+
async function writeFileContent(filepath, content) {
|
|
958
|
+
await ensureDir((0, import_node_path.dirname)(filepath));
|
|
959
|
+
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
960
|
+
}
|
|
961
|
+
async function fileExists(filepath) {
|
|
962
|
+
try {
|
|
963
|
+
await (0, import_promises2.stat)(filepath);
|
|
964
|
+
return true;
|
|
965
|
+
} catch {
|
|
966
|
+
return false;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
async function findFiles(dir, extension = ".md") {
|
|
970
|
+
try {
|
|
971
|
+
const files = await (0, import_promises2.readdir)(dir);
|
|
972
|
+
return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path.join)(dir, file));
|
|
973
|
+
} catch {
|
|
974
|
+
return [];
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
async function removeDirectory(dirPath) {
|
|
978
|
+
const dangerousPaths = [".", "/", "~", "src", "node_modules"];
|
|
979
|
+
if (dangerousPaths.includes(dirPath) || dirPath === "") {
|
|
980
|
+
console.warn(`Skipping deletion of dangerous path: ${dirPath}`);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
try {
|
|
984
|
+
if (await fileExists(dirPath)) {
|
|
985
|
+
await (0, import_promises2.rm)(dirPath, { recursive: true, force: true });
|
|
986
|
+
}
|
|
987
|
+
} catch (error) {
|
|
988
|
+
console.warn(`Failed to remove directory ${dirPath}:`, error);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
async function removeFile(filepath) {
|
|
992
|
+
try {
|
|
993
|
+
if (await fileExists(filepath)) {
|
|
994
|
+
await (0, import_promises2.rm)(filepath);
|
|
995
|
+
}
|
|
996
|
+
} catch (error) {
|
|
997
|
+
console.warn(`Failed to remove file ${filepath}:`, error);
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
async function removeClaudeGeneratedFiles() {
|
|
1001
|
+
const filesToRemove = ["CLAUDE.md", ".claude/memories"];
|
|
1002
|
+
for (const fileOrDir of filesToRemove) {
|
|
1003
|
+
if (fileOrDir.endsWith("/memories")) {
|
|
1004
|
+
await removeDirectory(fileOrDir);
|
|
1005
|
+
} else {
|
|
1006
|
+
await removeFile(fileOrDir);
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/utils/rules.ts
|
|
1012
|
+
function isToolSpecificRule(rule, targetTool) {
|
|
1013
|
+
const filename = rule.filename;
|
|
1014
|
+
const toolPatterns = {
|
|
1015
|
+
"augmentcode-legacy": /^specification-augmentcode-legacy-/i,
|
|
1016
|
+
augmentcode: /^specification-augmentcode-/i,
|
|
1017
|
+
copilot: /^specification-copilot-/i,
|
|
1018
|
+
cursor: /^specification-cursor-/i,
|
|
1019
|
+
cline: /^specification-cline-/i,
|
|
1020
|
+
claudecode: /^specification-claudecode-/i,
|
|
1021
|
+
roo: /^specification-roo-/i,
|
|
1022
|
+
geminicli: /^specification-geminicli-/i,
|
|
1023
|
+
kiro: /^specification-kiro-/i
|
|
1024
|
+
};
|
|
1025
|
+
for (const [tool, pattern] of Object.entries(toolPatterns)) {
|
|
1026
|
+
if (pattern.test(filename)) {
|
|
1027
|
+
return tool === targetTool;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
return true;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// src/cli/commands/config.ts
|
|
1034
|
+
async function configCommand(options = {}) {
|
|
1035
|
+
if (options.init) {
|
|
1036
|
+
await initConfig(options);
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
await showConfig();
|
|
1040
|
+
}
|
|
1041
|
+
async function showConfig() {
|
|
1042
|
+
console.log("Loading configuration...\n");
|
|
1043
|
+
try {
|
|
1044
|
+
const result = await loadConfig();
|
|
1045
|
+
if (result.isEmpty) {
|
|
1046
|
+
console.log("No configuration file found. Using default configuration.\n");
|
|
1047
|
+
} else {
|
|
1048
|
+
console.log(`Configuration loaded from: ${result.filepath}
|
|
1049
|
+
`);
|
|
1050
|
+
}
|
|
1051
|
+
console.log("Current configuration:");
|
|
1052
|
+
console.log("=====================");
|
|
1053
|
+
const config = result.config;
|
|
1054
|
+
console.log(`
|
|
1055
|
+
AI Rules Directory: ${config.aiRulesDir}`);
|
|
1056
|
+
console.log(`
|
|
1057
|
+
Default Targets: ${config.defaultTargets.join(", ")}`);
|
|
1058
|
+
if (config.exclude && config.exclude.length > 0) {
|
|
1059
|
+
console.log(`Excluded Targets: ${config.exclude.join(", ")}`);
|
|
1060
|
+
}
|
|
1061
|
+
console.log("\nOutput Paths:");
|
|
1062
|
+
for (const [tool, outputPath] of Object.entries(config.outputPaths)) {
|
|
1063
|
+
console.log(` ${tool}: ${outputPath}`);
|
|
1064
|
+
}
|
|
1065
|
+
if (config.baseDir) {
|
|
1066
|
+
const dirs = Array.isArray(config.baseDir) ? config.baseDir : [config.baseDir];
|
|
1067
|
+
console.log(`
|
|
1068
|
+
Base Directories: ${dirs.join(", ")}`);
|
|
1069
|
+
}
|
|
1070
|
+
console.log(`
|
|
1071
|
+
Verbose: ${config.verbose || false}`);
|
|
1072
|
+
console.log(`Delete before generate: ${config.delete || false}`);
|
|
1073
|
+
if (config.watch) {
|
|
1074
|
+
console.log("\nWatch Configuration:");
|
|
1075
|
+
console.log(` Enabled: ${config.watch.enabled || false}`);
|
|
1076
|
+
if (config.watch.interval) {
|
|
1077
|
+
console.log(` Interval: ${config.watch.interval}ms`);
|
|
1078
|
+
}
|
|
1079
|
+
if (config.watch.ignore && config.watch.ignore.length > 0) {
|
|
1080
|
+
console.log(` Ignore patterns: ${config.watch.ignore.join(", ")}`);
|
|
728
1081
|
}
|
|
729
1082
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
1083
|
+
console.log("\nTip: Use 'rulesync config init' to create a configuration file.");
|
|
1084
|
+
} catch (error) {
|
|
1085
|
+
console.error(
|
|
1086
|
+
"\u274C Failed to load configuration:",
|
|
1087
|
+
error instanceof Error ? error.message : String(error)
|
|
1088
|
+
);
|
|
1089
|
+
process.exit(1);
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
var FORMAT_CONFIG = {
|
|
1093
|
+
jsonc: {
|
|
1094
|
+
filename: "rulesync.jsonc",
|
|
1095
|
+
generator: generateJsoncConfig
|
|
1096
|
+
},
|
|
1097
|
+
ts: {
|
|
1098
|
+
filename: "rulesync.ts",
|
|
1099
|
+
generator: generateTsConfig
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
async function initConfig(options) {
|
|
1103
|
+
const validFormats = Object.keys(FORMAT_CONFIG);
|
|
1104
|
+
const selectedFormat = options.format || "jsonc";
|
|
1105
|
+
if (!validFormats.includes(selectedFormat)) {
|
|
1106
|
+
console.error(
|
|
1107
|
+
`\u274C Invalid format: ${selectedFormat}. Valid formats are: ${validFormats.join(", ")}`
|
|
1108
|
+
);
|
|
1109
|
+
process.exit(1);
|
|
1110
|
+
}
|
|
1111
|
+
const formatConfig = FORMAT_CONFIG[selectedFormat];
|
|
1112
|
+
const filename = formatConfig.filename;
|
|
1113
|
+
const configOptions = {};
|
|
1114
|
+
if (options.targets) {
|
|
1115
|
+
const targets = options.targets.split(",").map((t) => t.trim());
|
|
1116
|
+
const validTargets = [];
|
|
1117
|
+
for (const target of targets) {
|
|
1118
|
+
const result = ToolTargetSchema.safeParse(target);
|
|
1119
|
+
if (result.success) {
|
|
1120
|
+
validTargets.push(result.data);
|
|
1121
|
+
} else {
|
|
1122
|
+
console.error(`\u274C Invalid target: ${target}`);
|
|
1123
|
+
process.exit(1);
|
|
734
1124
|
}
|
|
735
1125
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
1126
|
+
configOptions.targets = validTargets;
|
|
1127
|
+
}
|
|
1128
|
+
if (options.exclude) {
|
|
1129
|
+
const excludes = options.exclude.split(",").map((t) => t.trim());
|
|
1130
|
+
const validExcludes = [];
|
|
1131
|
+
for (const exclude of excludes) {
|
|
1132
|
+
const result = ToolTargetSchema.safeParse(exclude);
|
|
1133
|
+
if (result.success) {
|
|
1134
|
+
validExcludes.push(result.data);
|
|
1135
|
+
} else {
|
|
1136
|
+
console.error(`\u274C Invalid exclude target: ${exclude}`);
|
|
1137
|
+
process.exit(1);
|
|
740
1138
|
}
|
|
741
1139
|
}
|
|
1140
|
+
configOptions.exclude = validExcludes;
|
|
1141
|
+
}
|
|
1142
|
+
if (options.aiRulesDir) {
|
|
1143
|
+
configOptions.aiRulesDir = options.aiRulesDir;
|
|
1144
|
+
}
|
|
1145
|
+
if (options.baseDir) {
|
|
1146
|
+
configOptions.baseDir = options.baseDir;
|
|
1147
|
+
}
|
|
1148
|
+
if (options.verbose !== void 0) {
|
|
1149
|
+
configOptions.verbose = options.verbose;
|
|
1150
|
+
}
|
|
1151
|
+
if (options.delete !== void 0) {
|
|
1152
|
+
configOptions.delete = options.delete;
|
|
1153
|
+
}
|
|
1154
|
+
const content = formatConfig.generator(configOptions);
|
|
1155
|
+
const filepath = import_node_path2.default.join(process.cwd(), filename);
|
|
1156
|
+
try {
|
|
1157
|
+
const fs2 = await import("fs/promises");
|
|
1158
|
+
await fs2.access(filepath);
|
|
1159
|
+
console.error(`\u274C Configuration file already exists: ${filepath}`);
|
|
1160
|
+
console.log("Remove the existing file or choose a different format.");
|
|
1161
|
+
process.exit(1);
|
|
1162
|
+
} catch {
|
|
1163
|
+
}
|
|
1164
|
+
try {
|
|
1165
|
+
(0, import_node_fs.writeFileSync)(filepath, content, "utf-8");
|
|
1166
|
+
console.log(`\u2705 Created configuration file: ${filepath}`);
|
|
1167
|
+
console.log("\nYou can now customize the configuration to fit your needs.");
|
|
1168
|
+
console.log("Run 'rulesync generate' to use the new configuration.");
|
|
1169
|
+
} catch (error) {
|
|
1170
|
+
console.error(
|
|
1171
|
+
`\u274C Failed to create configuration file: ${error instanceof Error ? error.message : String(error)}`
|
|
1172
|
+
);
|
|
1173
|
+
process.exit(1);
|
|
742
1174
|
}
|
|
743
|
-
return patterns;
|
|
744
1175
|
}
|
|
1176
|
+
function generateJsoncConfig(options) {
|
|
1177
|
+
if (options && Object.keys(options).length > 0) {
|
|
1178
|
+
return generateMinimalConfig(options);
|
|
1179
|
+
}
|
|
1180
|
+
return generateSampleConfig(options);
|
|
1181
|
+
}
|
|
1182
|
+
function generateTsConfig(options) {
|
|
1183
|
+
if (!options || Object.keys(options).length === 0) {
|
|
1184
|
+
return `import type { ConfigOptions } from "rulesync";
|
|
1185
|
+
|
|
1186
|
+
const config: ConfigOptions = {
|
|
1187
|
+
// List of tools to generate configurations for
|
|
1188
|
+
// Available: ${ALL_TOOL_TARGETS.join(", ")}
|
|
1189
|
+
targets: ${JSON.stringify(ALL_TOOL_TARGETS)},
|
|
1190
|
+
|
|
1191
|
+
// Custom output paths for specific tools
|
|
1192
|
+
// outputPaths: {
|
|
1193
|
+
// copilot: ".github/copilot-instructions.md",
|
|
1194
|
+
// },
|
|
1195
|
+
|
|
1196
|
+
// Delete existing files before generating
|
|
1197
|
+
// delete: false,
|
|
1198
|
+
|
|
1199
|
+
// Enable verbose output
|
|
1200
|
+
verbose: true,
|
|
1201
|
+
};
|
|
745
1202
|
|
|
746
|
-
|
|
747
|
-
var import_node_path2 = require("path");
|
|
748
|
-
async function generateKiroIgnoreFiles(rules, config, baseDir) {
|
|
749
|
-
const outputs = [];
|
|
750
|
-
const aiignoreContent = generateAiignoreContent(rules);
|
|
751
|
-
const outputPath = baseDir || process.cwd();
|
|
752
|
-
const filepath = (0, import_node_path2.join)(outputPath, ".aiignore");
|
|
753
|
-
outputs.push({
|
|
754
|
-
tool: "kiro",
|
|
755
|
-
filepath,
|
|
756
|
-
content: aiignoreContent
|
|
757
|
-
});
|
|
758
|
-
return outputs;
|
|
759
|
-
}
|
|
760
|
-
function generateAiignoreContent(rules) {
|
|
761
|
-
const lines = [
|
|
762
|
-
"# Generated by rulesync - Kiro AI-specific exclusions",
|
|
763
|
-
"# This file excludes files that can be in Git but shouldn't be read by the AI",
|
|
764
|
-
""
|
|
765
|
-
];
|
|
766
|
-
lines.push(
|
|
767
|
-
"# Data files AI shouldn't process",
|
|
768
|
-
"*.csv",
|
|
769
|
-
"*.tsv",
|
|
770
|
-
"*.sqlite",
|
|
771
|
-
"*.db",
|
|
772
|
-
"",
|
|
773
|
-
"# Large binary files",
|
|
774
|
-
"*.zip",
|
|
775
|
-
"*.tar.gz",
|
|
776
|
-
"*.rar",
|
|
777
|
-
"",
|
|
778
|
-
"# Sensitive documentation",
|
|
779
|
-
"internal-docs/",
|
|
780
|
-
"confidential/",
|
|
781
|
-
"",
|
|
782
|
-
"# Test data that might confuse AI",
|
|
783
|
-
"test/fixtures/large-*.json",
|
|
784
|
-
"benchmark-results/",
|
|
785
|
-
"",
|
|
786
|
-
"# Reinforce critical exclusions from .gitignore",
|
|
787
|
-
"*.pem",
|
|
788
|
-
"*.key",
|
|
789
|
-
".env*",
|
|
790
|
-
""
|
|
791
|
-
);
|
|
792
|
-
const rulePatterns = extractIgnorePatternsFromRules2(rules);
|
|
793
|
-
if (rulePatterns.length > 0) {
|
|
794
|
-
lines.push("# Project-specific exclusions from rulesync rules");
|
|
795
|
-
lines.push(...rulePatterns);
|
|
796
|
-
lines.push("");
|
|
1203
|
+
export default config;`;
|
|
797
1204
|
}
|
|
798
|
-
|
|
1205
|
+
const configLines = [];
|
|
1206
|
+
if (options.targets) {
|
|
1207
|
+
configLines.push(` targets: ${JSON.stringify(options.targets)}`);
|
|
1208
|
+
}
|
|
1209
|
+
if (options.exclude) {
|
|
1210
|
+
configLines.push(` exclude: ${JSON.stringify(options.exclude)}`);
|
|
1211
|
+
}
|
|
1212
|
+
if (options.aiRulesDir) {
|
|
1213
|
+
configLines.push(` aiRulesDir: "${options.aiRulesDir}"`);
|
|
1214
|
+
}
|
|
1215
|
+
if (options.outputPaths) {
|
|
1216
|
+
const pathsStr = JSON.stringify(options.outputPaths, null, 4).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
1217
|
+
configLines.push(` outputPaths: ${pathsStr}`);
|
|
1218
|
+
}
|
|
1219
|
+
if (options.baseDir) {
|
|
1220
|
+
configLines.push(` baseDir: ${JSON.stringify(options.baseDir)}`);
|
|
1221
|
+
}
|
|
1222
|
+
if (options.delete !== void 0) {
|
|
1223
|
+
configLines.push(` delete: ${options.delete}`);
|
|
1224
|
+
}
|
|
1225
|
+
if (options.verbose !== void 0) {
|
|
1226
|
+
configLines.push(` verbose: ${options.verbose}`);
|
|
1227
|
+
}
|
|
1228
|
+
if (options.watch) {
|
|
1229
|
+
const watchStr = JSON.stringify(options.watch, null, 4).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
1230
|
+
configLines.push(` watch: ${watchStr}`);
|
|
1231
|
+
}
|
|
1232
|
+
const configContent = `import type { ConfigOptions } from "rulesync";
|
|
1233
|
+
|
|
1234
|
+
const config: ConfigOptions = {
|
|
1235
|
+
${configLines.join(",\n")},
|
|
1236
|
+
};
|
|
1237
|
+
|
|
1238
|
+
export default config;
|
|
1239
|
+
`;
|
|
1240
|
+
return configContent;
|
|
799
1241
|
}
|
|
800
|
-
|
|
1242
|
+
|
|
1243
|
+
// src/cli/commands/generate.ts
|
|
1244
|
+
var import_node_path12 = require("path");
|
|
1245
|
+
|
|
1246
|
+
// src/generators/ignore/shared-factory.ts
|
|
1247
|
+
var import_node_path3 = require("path");
|
|
1248
|
+
|
|
1249
|
+
// src/generators/ignore/shared-helpers.ts
|
|
1250
|
+
function extractIgnorePatternsFromRules(rules) {
|
|
801
1251
|
const patterns = [];
|
|
802
1252
|
for (const rule of rules) {
|
|
803
1253
|
if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
|
|
@@ -815,20 +1265,28 @@ function extractIgnorePatternsFromRules2(rules) {
|
|
|
815
1265
|
}
|
|
816
1266
|
function shouldExcludeFromAI(glob) {
|
|
817
1267
|
const excludePatterns = [
|
|
818
|
-
//
|
|
819
|
-
"**/
|
|
1268
|
+
// Large generated files that slow indexing
|
|
1269
|
+
"**/assets/generated/**",
|
|
1270
|
+
"**/public/build/**",
|
|
1271
|
+
// Test fixtures with potentially sensitive data
|
|
820
1272
|
"**/tests/fixtures/**",
|
|
1273
|
+
"**/test/fixtures/**",
|
|
821
1274
|
"**/*.fixture.*",
|
|
822
|
-
// Build
|
|
1275
|
+
// Build outputs that provide little value for AI context
|
|
823
1276
|
"**/dist/**",
|
|
824
1277
|
"**/build/**",
|
|
825
1278
|
"**/coverage/**",
|
|
826
1279
|
// Configuration that might contain sensitive data
|
|
827
1280
|
"**/config/production/**",
|
|
1281
|
+
"**/config/secrets/**",
|
|
828
1282
|
"**/config/prod/**",
|
|
1283
|
+
"**/deploy/prod/**",
|
|
829
1284
|
"**/*.prod.*",
|
|
830
|
-
//
|
|
1285
|
+
// Internal documentation that might be sensitive
|
|
831
1286
|
"**/internal/**",
|
|
1287
|
+
"**/internal-docs/**",
|
|
1288
|
+
"**/proprietary/**",
|
|
1289
|
+
"**/personal-notes/**",
|
|
832
1290
|
"**/private/**",
|
|
833
1291
|
"**/confidential/**"
|
|
834
1292
|
];
|
|
@@ -848,6 +1306,18 @@ function extractIgnorePatternsFromContent(content) {
|
|
|
848
1306
|
patterns.push(pattern);
|
|
849
1307
|
}
|
|
850
1308
|
}
|
|
1309
|
+
if (trimmed.startsWith("# AUGMENT_IGNORE:") || trimmed.startsWith("# augmentignore:")) {
|
|
1310
|
+
const pattern = trimmed.replace(/^# (AUGMENT_IGNORE|augmentignore):\s*/, "").trim();
|
|
1311
|
+
if (pattern) {
|
|
1312
|
+
patterns.push(pattern);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
if (trimmed.startsWith("# AUGMENT_INCLUDE:") || trimmed.startsWith("# augmentinclude:")) {
|
|
1316
|
+
const pattern = trimmed.replace(/^# (AUGMENT_INCLUDE|augmentinclude):\s*/, "").trim();
|
|
1317
|
+
if (pattern) {
|
|
1318
|
+
patterns.push(`!${pattern}`);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
851
1321
|
if (trimmed.includes("exclude") || trimmed.includes("ignore")) {
|
|
852
1322
|
const matches = trimmed.match(/['"`]([^'"`]+\.(log|tmp|cache|temp))['"`]/g);
|
|
853
1323
|
if (matches) {
|
|
@@ -855,7 +1325,369 @@ function extractIgnorePatternsFromContent(content) {
|
|
|
855
1325
|
}
|
|
856
1326
|
}
|
|
857
1327
|
}
|
|
858
|
-
return patterns;
|
|
1328
|
+
return patterns;
|
|
1329
|
+
}
|
|
1330
|
+
function extractAugmentCodeIgnorePatternsFromContent(content) {
|
|
1331
|
+
const patterns = [];
|
|
1332
|
+
const lines = content.split("\n");
|
|
1333
|
+
for (const line of lines) {
|
|
1334
|
+
const trimmed = line.trim();
|
|
1335
|
+
if (trimmed.startsWith("# AUGMENT_IGNORE:") || trimmed.startsWith("# augmentignore:")) {
|
|
1336
|
+
const pattern = trimmed.replace(/^# (AUGMENT_IGNORE|augmentignore):\s*/, "").trim();
|
|
1337
|
+
if (pattern) {
|
|
1338
|
+
patterns.push(pattern);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
if (trimmed.startsWith("# AUGMENT_INCLUDE:") || trimmed.startsWith("# augmentinclude:")) {
|
|
1342
|
+
const pattern = trimmed.replace(/^# (AUGMENT_INCLUDE|augmentinclude):\s*/, "").trim();
|
|
1343
|
+
if (pattern) {
|
|
1344
|
+
patterns.push(`!${pattern}`);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
if (trimmed.includes("large file") || trimmed.includes("binary") || trimmed.includes("media")) {
|
|
1348
|
+
const regex = /['"`]([^'"`]+\.(mp4|avi|zip|tar\.gz|rar|pdf|doc|xlsx))['"`]/g;
|
|
1349
|
+
let match;
|
|
1350
|
+
while ((match = regex.exec(trimmed)) !== null) {
|
|
1351
|
+
if (match[1]) {
|
|
1352
|
+
patterns.push(match[1]);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return patterns;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// src/generators/ignore/shared-factory.ts
|
|
1361
|
+
function generateIgnoreFile(rules, config, ignoreConfig, baseDir) {
|
|
1362
|
+
const outputs = [];
|
|
1363
|
+
const content = generateIgnoreContent(rules, ignoreConfig);
|
|
1364
|
+
const outputPath = baseDir || process.cwd();
|
|
1365
|
+
const filepath = (0, import_node_path3.join)(outputPath, ignoreConfig.filename);
|
|
1366
|
+
outputs.push({
|
|
1367
|
+
tool: ignoreConfig.tool,
|
|
1368
|
+
filepath,
|
|
1369
|
+
content
|
|
1370
|
+
});
|
|
1371
|
+
return outputs;
|
|
1372
|
+
}
|
|
1373
|
+
function generateIgnoreContent(rules, config) {
|
|
1374
|
+
const lines = [];
|
|
1375
|
+
lines.push(...config.header);
|
|
1376
|
+
lines.push("");
|
|
1377
|
+
if (config.includeCommonPatterns) {
|
|
1378
|
+
lines.push(...getCommonIgnorePatterns());
|
|
1379
|
+
}
|
|
1380
|
+
if (config.corePatterns.length > 0) {
|
|
1381
|
+
lines.push(...config.corePatterns);
|
|
1382
|
+
lines.push("");
|
|
1383
|
+
}
|
|
1384
|
+
const rulePatterns = extractIgnorePatternsFromRules(rules);
|
|
1385
|
+
const customPatterns = config.customPatternProcessor ? config.customPatternProcessor(rules) : [];
|
|
1386
|
+
const allPatterns = [...rulePatterns, ...customPatterns];
|
|
1387
|
+
if (allPatterns.length > 0) {
|
|
1388
|
+
const headerText = config.projectPatternsHeader || "# \u2500\u2500\u2500\u2500\u2500 Project-specific exclusions from rulesync rules \u2500\u2500\u2500\u2500\u2500";
|
|
1389
|
+
lines.push(headerText);
|
|
1390
|
+
lines.push(...allPatterns);
|
|
1391
|
+
lines.push("");
|
|
1392
|
+
}
|
|
1393
|
+
return lines.join("\n");
|
|
1394
|
+
}
|
|
1395
|
+
function getCommonIgnorePatterns() {
|
|
1396
|
+
return [
|
|
1397
|
+
"# \u2500\u2500\u2500\u2500\u2500 Source Control Metadata \u2500\u2500\u2500\u2500\u2500",
|
|
1398
|
+
".git/",
|
|
1399
|
+
".svn/",
|
|
1400
|
+
".hg/",
|
|
1401
|
+
".idea/",
|
|
1402
|
+
"*.iml",
|
|
1403
|
+
".vscode/settings.json",
|
|
1404
|
+
"",
|
|
1405
|
+
"# \u2500\u2500\u2500\u2500\u2500 Build Artifacts \u2500\u2500\u2500\u2500\u2500",
|
|
1406
|
+
"/out/",
|
|
1407
|
+
"/dist/",
|
|
1408
|
+
"/target/",
|
|
1409
|
+
"/build/",
|
|
1410
|
+
"*.class",
|
|
1411
|
+
"*.jar",
|
|
1412
|
+
"*.war",
|
|
1413
|
+
"",
|
|
1414
|
+
"# \u2500\u2500\u2500\u2500\u2500 Secrets & Credentials \u2500\u2500\u2500\u2500\u2500",
|
|
1415
|
+
"# Environment files",
|
|
1416
|
+
".env",
|
|
1417
|
+
".env.*",
|
|
1418
|
+
"!.env.example",
|
|
1419
|
+
"",
|
|
1420
|
+
"# Key material",
|
|
1421
|
+
"*.pem",
|
|
1422
|
+
"*.key",
|
|
1423
|
+
"*.crt",
|
|
1424
|
+
"*.p12",
|
|
1425
|
+
"*.pfx",
|
|
1426
|
+
"*.der",
|
|
1427
|
+
"id_rsa*",
|
|
1428
|
+
"id_dsa*",
|
|
1429
|
+
"*.ppk",
|
|
1430
|
+
"",
|
|
1431
|
+
"# Cloud and service configs",
|
|
1432
|
+
"aws-credentials.json",
|
|
1433
|
+
"gcp-service-account*.json",
|
|
1434
|
+
"azure-credentials.json",
|
|
1435
|
+
"secrets/**",
|
|
1436
|
+
"config/secrets/",
|
|
1437
|
+
"**/secrets/",
|
|
1438
|
+
"",
|
|
1439
|
+
"# Database credentials",
|
|
1440
|
+
"database.yml",
|
|
1441
|
+
"**/database/config.*",
|
|
1442
|
+
"",
|
|
1443
|
+
"# API keys and tokens",
|
|
1444
|
+
"**/apikeys/",
|
|
1445
|
+
"**/*_token*",
|
|
1446
|
+
"**/*_secret*",
|
|
1447
|
+
"**/*api_key*",
|
|
1448
|
+
"",
|
|
1449
|
+
"# \u2500\u2500\u2500\u2500\u2500 Infrastructure & Deployment \u2500\u2500\u2500\u2500\u2500",
|
|
1450
|
+
"# Terraform state",
|
|
1451
|
+
"*.tfstate",
|
|
1452
|
+
"*.tfstate.*",
|
|
1453
|
+
".terraform/",
|
|
1454
|
+
"",
|
|
1455
|
+
"# Kubernetes secrets",
|
|
1456
|
+
"**/k8s/**/secret*.yaml",
|
|
1457
|
+
"**/kubernetes/**/secret*.yaml",
|
|
1458
|
+
"",
|
|
1459
|
+
"# Docker secrets",
|
|
1460
|
+
"docker-compose.override.yml",
|
|
1461
|
+
"**/docker/secrets/",
|
|
1462
|
+
"",
|
|
1463
|
+
"# \u2500\u2500\u2500\u2500\u2500 Logs & Runtime Data \u2500\u2500\u2500\u2500\u2500",
|
|
1464
|
+
"*.log",
|
|
1465
|
+
"*.tmp",
|
|
1466
|
+
"*.cache",
|
|
1467
|
+
"logs/",
|
|
1468
|
+
"/var/log/",
|
|
1469
|
+
"coverage/",
|
|
1470
|
+
".nyc_output/",
|
|
1471
|
+
"",
|
|
1472
|
+
"# \u2500\u2500\u2500\u2500\u2500 Large Data Files \u2500\u2500\u2500\u2500\u2500",
|
|
1473
|
+
"*.csv",
|
|
1474
|
+
"*.xlsx",
|
|
1475
|
+
"*.sqlite",
|
|
1476
|
+
"*.db",
|
|
1477
|
+
"*.dump",
|
|
1478
|
+
"data/",
|
|
1479
|
+
"datasets/",
|
|
1480
|
+
"",
|
|
1481
|
+
"# \u2500\u2500\u2500\u2500\u2500 Node.js Specific \u2500\u2500\u2500\u2500\u2500",
|
|
1482
|
+
"node_modules/",
|
|
1483
|
+
".pnpm-store/",
|
|
1484
|
+
".yarn/",
|
|
1485
|
+
".next/",
|
|
1486
|
+
".nuxt/",
|
|
1487
|
+
".cache/",
|
|
1488
|
+
".parcel-cache/",
|
|
1489
|
+
"",
|
|
1490
|
+
"# \u2500\u2500\u2500\u2500\u2500 Python Specific \u2500\u2500\u2500\u2500\u2500",
|
|
1491
|
+
"__pycache__/",
|
|
1492
|
+
"*.pyc",
|
|
1493
|
+
"*.pyo",
|
|
1494
|
+
"*.pyd",
|
|
1495
|
+
".Python",
|
|
1496
|
+
"venv/",
|
|
1497
|
+
".venv/",
|
|
1498
|
+
"env/",
|
|
1499
|
+
".env/",
|
|
1500
|
+
"",
|
|
1501
|
+
"# \u2500\u2500\u2500\u2500\u2500 Java Specific \u2500\u2500\u2500\u2500\u2500",
|
|
1502
|
+
"*.class",
|
|
1503
|
+
"*.jar",
|
|
1504
|
+
"*.war",
|
|
1505
|
+
"target/",
|
|
1506
|
+
""
|
|
1507
|
+
];
|
|
1508
|
+
}
|
|
1509
|
+
var ignoreConfigs = {
|
|
1510
|
+
junie: {
|
|
1511
|
+
tool: "junie",
|
|
1512
|
+
filename: ".aiignore",
|
|
1513
|
+
header: [
|
|
1514
|
+
"# Generated by rulesync - JetBrains Junie AI ignore file",
|
|
1515
|
+
"# This file controls which files the AI can access automatically",
|
|
1516
|
+
"# AI must ask before reading or editing matched files/directories"
|
|
1517
|
+
],
|
|
1518
|
+
corePatterns: [
|
|
1519
|
+
"# \u2500\u2500\u2500\u2500\u2500 Allow specific source files (uncomment as needed) \u2500\u2500\u2500\u2500\u2500",
|
|
1520
|
+
"# !src/**/*.ts",
|
|
1521
|
+
"# !src/**/*.js",
|
|
1522
|
+
"# !lib/**/*.py",
|
|
1523
|
+
"# !src/main/**/*.java"
|
|
1524
|
+
],
|
|
1525
|
+
includeCommonPatterns: true
|
|
1526
|
+
},
|
|
1527
|
+
kiro: {
|
|
1528
|
+
tool: "kiro",
|
|
1529
|
+
filename: ".aiignore",
|
|
1530
|
+
header: [
|
|
1531
|
+
"# Generated by rulesync - Kiro AI-specific exclusions",
|
|
1532
|
+
"# This file excludes files that can be in Git but shouldn't be read by the AI"
|
|
1533
|
+
],
|
|
1534
|
+
corePatterns: [
|
|
1535
|
+
"# Data files AI shouldn't process",
|
|
1536
|
+
"*.csv",
|
|
1537
|
+
"*.tsv",
|
|
1538
|
+
"*.sqlite",
|
|
1539
|
+
"*.db",
|
|
1540
|
+
"",
|
|
1541
|
+
"# Large binary files",
|
|
1542
|
+
"*.zip",
|
|
1543
|
+
"*.tar.gz",
|
|
1544
|
+
"*.rar",
|
|
1545
|
+
"",
|
|
1546
|
+
"# Sensitive documentation",
|
|
1547
|
+
"internal-docs/",
|
|
1548
|
+
"confidential/",
|
|
1549
|
+
"",
|
|
1550
|
+
"# Test data that might confuse AI",
|
|
1551
|
+
"test/fixtures/large-*.json",
|
|
1552
|
+
"benchmark-results/",
|
|
1553
|
+
"",
|
|
1554
|
+
"# Reinforce critical exclusions from .gitignore",
|
|
1555
|
+
"*.pem",
|
|
1556
|
+
"*.key",
|
|
1557
|
+
".env*"
|
|
1558
|
+
],
|
|
1559
|
+
includeCommonPatterns: false,
|
|
1560
|
+
projectPatternsHeader: "# Project-specific exclusions from rulesync rules"
|
|
1561
|
+
},
|
|
1562
|
+
augmentcode: {
|
|
1563
|
+
tool: "augmentcode",
|
|
1564
|
+
filename: ".augmentignore",
|
|
1565
|
+
header: [
|
|
1566
|
+
"# Generated by rulesync - AugmentCode ignore patterns",
|
|
1567
|
+
"# AugmentCode uses a two-tier approach: .gitignore first, then .augmentignore",
|
|
1568
|
+
"# This file provides Augment-specific exclusions and re-inclusions"
|
|
1569
|
+
],
|
|
1570
|
+
corePatterns: [
|
|
1571
|
+
"# Security and Secrets (critical exclusions)",
|
|
1572
|
+
"# Environment files",
|
|
1573
|
+
".env*",
|
|
1574
|
+
"",
|
|
1575
|
+
"# Private keys and certificates",
|
|
1576
|
+
"*.pem",
|
|
1577
|
+
"*.key",
|
|
1578
|
+
"*.p12",
|
|
1579
|
+
"*.crt",
|
|
1580
|
+
"*.der",
|
|
1581
|
+
"",
|
|
1582
|
+
"# SSH keys",
|
|
1583
|
+
"id_rsa*",
|
|
1584
|
+
"id_dsa*",
|
|
1585
|
+
"",
|
|
1586
|
+
"# AWS credentials",
|
|
1587
|
+
".aws/",
|
|
1588
|
+
"aws-exports.js",
|
|
1589
|
+
"",
|
|
1590
|
+
"# API keys and tokens",
|
|
1591
|
+
"**/apikeys/",
|
|
1592
|
+
"**/*_token*",
|
|
1593
|
+
"**/*_secret*",
|
|
1594
|
+
"",
|
|
1595
|
+
"# Build Artifacts and Dependencies",
|
|
1596
|
+
"# Build outputs",
|
|
1597
|
+
"dist/",
|
|
1598
|
+
"build/",
|
|
1599
|
+
"out/",
|
|
1600
|
+
"target/",
|
|
1601
|
+
"",
|
|
1602
|
+
"# Dependencies",
|
|
1603
|
+
"node_modules/",
|
|
1604
|
+
"venv/",
|
|
1605
|
+
"*.egg-info/",
|
|
1606
|
+
"",
|
|
1607
|
+
"# Logs",
|
|
1608
|
+
"*.log",
|
|
1609
|
+
"logs/",
|
|
1610
|
+
"",
|
|
1611
|
+
"# Temporary files",
|
|
1612
|
+
"*.tmp",
|
|
1613
|
+
"*.swp",
|
|
1614
|
+
"*.swo",
|
|
1615
|
+
"*~",
|
|
1616
|
+
"",
|
|
1617
|
+
"# Large Files and Media",
|
|
1618
|
+
"# Binary files",
|
|
1619
|
+
"*.jar",
|
|
1620
|
+
"*.png",
|
|
1621
|
+
"*.jpg",
|
|
1622
|
+
"*.jpeg",
|
|
1623
|
+
"*.gif",
|
|
1624
|
+
"*.mp4",
|
|
1625
|
+
"*.avi",
|
|
1626
|
+
"*.zip",
|
|
1627
|
+
"*.tar.gz",
|
|
1628
|
+
"*.rar",
|
|
1629
|
+
"",
|
|
1630
|
+
"# Database files",
|
|
1631
|
+
"*.sqlite",
|
|
1632
|
+
"*.db",
|
|
1633
|
+
"*.mdb",
|
|
1634
|
+
"",
|
|
1635
|
+
"# Data files",
|
|
1636
|
+
"*.csv",
|
|
1637
|
+
"*.tsv",
|
|
1638
|
+
"*.xlsx",
|
|
1639
|
+
"",
|
|
1640
|
+
"# Performance Optimization",
|
|
1641
|
+
"# Exclude files that are too large for effective AI processing",
|
|
1642
|
+
"**/*.{mp4,avi,mov,mkv}",
|
|
1643
|
+
"**/*.{zip,tar,gz,rar}",
|
|
1644
|
+
"**/*.{pdf,doc,docx}",
|
|
1645
|
+
"**/logs/**/*.log",
|
|
1646
|
+
"",
|
|
1647
|
+
"# But include small configuration files",
|
|
1648
|
+
"!**/config.{json,yaml,yml}",
|
|
1649
|
+
"",
|
|
1650
|
+
"# Team Collaboration",
|
|
1651
|
+
"# Exclude personal IDE settings",
|
|
1652
|
+
".vscode/settings.json",
|
|
1653
|
+
".idea/workspace.xml",
|
|
1654
|
+
"",
|
|
1655
|
+
"# But include shared team settings",
|
|
1656
|
+
"!.vscode/extensions.json",
|
|
1657
|
+
"!.idea/codeStyles/",
|
|
1658
|
+
"",
|
|
1659
|
+
"# Exclude test fixtures with sensitive data",
|
|
1660
|
+
"tests/fixtures/real-data/**",
|
|
1661
|
+
"",
|
|
1662
|
+
"# Re-include important documentation",
|
|
1663
|
+
"!vendor/*/README.md",
|
|
1664
|
+
"!third-party/*/LICENSE"
|
|
1665
|
+
],
|
|
1666
|
+
includeCommonPatterns: false,
|
|
1667
|
+
projectPatternsHeader: "# Project-specific patterns from rulesync rules",
|
|
1668
|
+
customPatternProcessor: (rules) => {
|
|
1669
|
+
const augmentPatterns = [];
|
|
1670
|
+
for (const rule of rules) {
|
|
1671
|
+
augmentPatterns.push(...extractAugmentCodeIgnorePatternsFromContent(rule.content));
|
|
1672
|
+
}
|
|
1673
|
+
return augmentPatterns;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
|
|
1678
|
+
// src/generators/ignore/augmentcode.ts
|
|
1679
|
+
async function generateAugmentCodeIgnoreFiles(rules, config, baseDir) {
|
|
1680
|
+
return generateIgnoreFile(rules, config, ignoreConfigs.augmentcode, baseDir);
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
// src/generators/ignore/junie.ts
|
|
1684
|
+
async function generateJunieIgnoreFiles(rules, config, baseDir) {
|
|
1685
|
+
return generateIgnoreFile(rules, config, ignoreConfigs.junie, baseDir);
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
// src/generators/ignore/kiro.ts
|
|
1689
|
+
async function generateKiroIgnoreFiles(rules, config, baseDir) {
|
|
1690
|
+
return generateIgnoreFile(rules, config, ignoreConfigs.kiro, baseDir);
|
|
859
1691
|
}
|
|
860
1692
|
|
|
861
1693
|
// src/generators/rules/augmentcode.ts
|
|
@@ -867,75 +1699,6 @@ var import_node_path5 = require("path");
|
|
|
867
1699
|
// src/utils/ignore.ts
|
|
868
1700
|
var import_node_path4 = require("path");
|
|
869
1701
|
var import_micromatch = __toESM(require("micromatch"), 1);
|
|
870
|
-
|
|
871
|
-
// src/utils/file.ts
|
|
872
|
-
var import_promises2 = require("fs/promises");
|
|
873
|
-
var import_node_path3 = require("path");
|
|
874
|
-
async function ensureDir(dirPath) {
|
|
875
|
-
try {
|
|
876
|
-
await (0, import_promises2.stat)(dirPath);
|
|
877
|
-
} catch {
|
|
878
|
-
await (0, import_promises2.mkdir)(dirPath, { recursive: true });
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
async function readFileContent(filepath) {
|
|
882
|
-
return (0, import_promises2.readFile)(filepath, "utf-8");
|
|
883
|
-
}
|
|
884
|
-
async function writeFileContent(filepath, content) {
|
|
885
|
-
await ensureDir((0, import_node_path3.dirname)(filepath));
|
|
886
|
-
await (0, import_promises2.writeFile)(filepath, content, "utf-8");
|
|
887
|
-
}
|
|
888
|
-
async function fileExists(filepath) {
|
|
889
|
-
try {
|
|
890
|
-
await (0, import_promises2.stat)(filepath);
|
|
891
|
-
return true;
|
|
892
|
-
} catch {
|
|
893
|
-
return false;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
async function findFiles(dir, extension = ".md") {
|
|
897
|
-
try {
|
|
898
|
-
const files = await (0, import_promises2.readdir)(dir);
|
|
899
|
-
return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path3.join)(dir, file));
|
|
900
|
-
} catch {
|
|
901
|
-
return [];
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
async function removeDirectory(dirPath) {
|
|
905
|
-
const dangerousPaths = [".", "/", "~", "src", "node_modules"];
|
|
906
|
-
if (dangerousPaths.includes(dirPath) || dirPath === "") {
|
|
907
|
-
console.warn(`Skipping deletion of dangerous path: ${dirPath}`);
|
|
908
|
-
return;
|
|
909
|
-
}
|
|
910
|
-
try {
|
|
911
|
-
if (await fileExists(dirPath)) {
|
|
912
|
-
await (0, import_promises2.rm)(dirPath, { recursive: true, force: true });
|
|
913
|
-
}
|
|
914
|
-
} catch (error) {
|
|
915
|
-
console.warn(`Failed to remove directory ${dirPath}:`, error);
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
async function removeFile(filepath) {
|
|
919
|
-
try {
|
|
920
|
-
if (await fileExists(filepath)) {
|
|
921
|
-
await (0, import_promises2.rm)(filepath);
|
|
922
|
-
}
|
|
923
|
-
} catch (error) {
|
|
924
|
-
console.warn(`Failed to remove file ${filepath}:`, error);
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
async function removeClaudeGeneratedFiles() {
|
|
928
|
-
const filesToRemove = ["CLAUDE.md", ".claude/memories"];
|
|
929
|
-
for (const fileOrDir of filesToRemove) {
|
|
930
|
-
if (fileOrDir.endsWith("/memories")) {
|
|
931
|
-
await removeDirectory(fileOrDir);
|
|
932
|
-
} else {
|
|
933
|
-
await removeFile(fileOrDir);
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
// src/utils/ignore.ts
|
|
939
1702
|
var cachedIgnorePatterns = null;
|
|
940
1703
|
async function loadIgnorePatterns(baseDir = process.cwd()) {
|
|
941
1704
|
if (cachedIgnorePatterns) {
|
|
@@ -1014,16 +1777,60 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
|
|
|
1014
1777
|
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1015
1778
|
if (ignorePatterns.patterns.length > 0) {
|
|
1016
1779
|
const ignorePath = baseDir ? (0, import_node_path5.join)(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
|
|
1017
|
-
const ignoreContent =
|
|
1780
|
+
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
|
|
1781
|
+
outputs.push({
|
|
1782
|
+
tool: generatorConfig.tool,
|
|
1783
|
+
filepath: ignorePath,
|
|
1784
|
+
content: ignoreContent
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
return outputs;
|
|
1788
|
+
}
|
|
1789
|
+
async function generateComplexRules(rules, config, generatorConfig, baseDir) {
|
|
1790
|
+
const outputs = [];
|
|
1791
|
+
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
1792
|
+
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
1793
|
+
const rootRule = rootRules[0];
|
|
1794
|
+
if (generatorConfig.generateDetailContent && generatorConfig.detailSubDir) {
|
|
1795
|
+
for (const rule of detailRules) {
|
|
1796
|
+
const content = generatorConfig.generateDetailContent(rule);
|
|
1797
|
+
const filepath = baseDir ? (0, import_node_path5.join)(baseDir, generatorConfig.detailSubDir, `${rule.filename}.md`) : (0, import_node_path5.join)(generatorConfig.detailSubDir, `${rule.filename}.md`);
|
|
1798
|
+
outputs.push({
|
|
1799
|
+
tool: generatorConfig.tool,
|
|
1800
|
+
filepath,
|
|
1801
|
+
content
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
if (generatorConfig.generateRootContent && generatorConfig.rootFilePath) {
|
|
1806
|
+
const rootContent = generatorConfig.generateRootContent(rootRule, detailRules, baseDir);
|
|
1807
|
+
const rootFilepath = baseDir ? (0, import_node_path5.join)(baseDir, generatorConfig.rootFilePath) : generatorConfig.rootFilePath;
|
|
1808
|
+
outputs.push({
|
|
1809
|
+
tool: generatorConfig.tool,
|
|
1810
|
+
filepath: rootFilepath,
|
|
1811
|
+
content: rootContent
|
|
1812
|
+
});
|
|
1813
|
+
}
|
|
1814
|
+
const ignorePatterns = await loadIgnorePatterns(baseDir);
|
|
1815
|
+
if (ignorePatterns.patterns.length > 0) {
|
|
1816
|
+
const ignorePath = baseDir ? (0, import_node_path5.join)(baseDir, generatorConfig.ignoreFileName) : generatorConfig.ignoreFileName;
|
|
1817
|
+
const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
|
|
1018
1818
|
outputs.push({
|
|
1019
1819
|
tool: generatorConfig.tool,
|
|
1020
1820
|
filepath: ignorePath,
|
|
1021
1821
|
content: ignoreContent
|
|
1022
1822
|
});
|
|
1823
|
+
if (generatorConfig.updateAdditionalConfig) {
|
|
1824
|
+
const additionalOutputs = await generatorConfig.updateAdditionalConfig(
|
|
1825
|
+
ignorePatterns.patterns,
|
|
1826
|
+
baseDir
|
|
1827
|
+
);
|
|
1828
|
+
outputs.push(...additionalOutputs);
|
|
1829
|
+
}
|
|
1023
1830
|
}
|
|
1024
1831
|
return outputs;
|
|
1025
1832
|
}
|
|
1026
|
-
function
|
|
1833
|
+
function generateIgnoreFile2(patterns, tool) {
|
|
1027
1834
|
const lines = [
|
|
1028
1835
|
"# Generated by rulesync from .rulesyncignore",
|
|
1029
1836
|
"# This file is automatically generated. Do not edit manually."
|
|
@@ -1110,19 +1917,6 @@ function generateLegacyGuidelinesFile(allRules) {
|
|
|
1110
1917
|
|
|
1111
1918
|
// src/generators/rules/claudecode.ts
|
|
1112
1919
|
var import_node_path7 = require("path");
|
|
1113
|
-
|
|
1114
|
-
// src/types/claudecode.ts
|
|
1115
|
-
var import_mini2 = require("zod/mini");
|
|
1116
|
-
var ClaudeSettingsSchema = import_mini2.z.looseObject({
|
|
1117
|
-
permissions: import_mini2.z._default(
|
|
1118
|
-
import_mini2.z.looseObject({
|
|
1119
|
-
deny: import_mini2.z._default(import_mini2.z.array(import_mini2.z.string()), [])
|
|
1120
|
-
}),
|
|
1121
|
-
{ deny: [] }
|
|
1122
|
-
)
|
|
1123
|
-
});
|
|
1124
|
-
|
|
1125
|
-
// src/generators/rules/claudecode.ts
|
|
1126
1920
|
async function generateClaudecodeConfig(rules, config, baseDir) {
|
|
1127
1921
|
const outputs = [];
|
|
1128
1922
|
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
@@ -1327,39 +2121,18 @@ function determineCursorRuleType(frontmatter) {
|
|
|
1327
2121
|
}
|
|
1328
2122
|
|
|
1329
2123
|
// src/generators/rules/geminicli.ts
|
|
1330
|
-
var import_node_path10 = require("path");
|
|
1331
2124
|
async function generateGeminiConfig(rules, config, baseDir) {
|
|
1332
|
-
const
|
|
1333
|
-
const rootRule = rules.find((rule) => rule.frontmatter.root === true);
|
|
1334
|
-
const memoryRules = rules.filter((rule) => rule.frontmatter.root === false);
|
|
1335
|
-
for (const rule of memoryRules) {
|
|
1336
|
-
const content = generateGeminiMemoryMarkdown(rule);
|
|
1337
|
-
const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.geminicli) : config.outputPaths.geminicli;
|
|
1338
|
-
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
1339
|
-
outputs.push({
|
|
1340
|
-
tool: "geminicli",
|
|
1341
|
-
filepath,
|
|
1342
|
-
content
|
|
1343
|
-
});
|
|
1344
|
-
}
|
|
1345
|
-
const rootContent = generateGeminiRootMarkdown(rootRule, memoryRules, baseDir);
|
|
1346
|
-
const rootFilepath = baseDir ? (0, import_node_path10.join)(baseDir, "GEMINI.md") : "GEMINI.md";
|
|
1347
|
-
outputs.push({
|
|
2125
|
+
const generatorConfig = {
|
|
1348
2126
|
tool: "geminicli",
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
filepath: aiexcludePath,
|
|
1359
|
-
content: aiexcludeContent
|
|
1360
|
-
});
|
|
1361
|
-
}
|
|
1362
|
-
return outputs;
|
|
2127
|
+
fileExtension: ".md",
|
|
2128
|
+
ignoreFileName: ".aiexclude",
|
|
2129
|
+
generateContent: generateGeminiMemoryMarkdown,
|
|
2130
|
+
generateDetailContent: generateGeminiMemoryMarkdown,
|
|
2131
|
+
generateRootContent: generateGeminiRootMarkdown,
|
|
2132
|
+
rootFilePath: "GEMINI.md",
|
|
2133
|
+
detailSubDir: ".gemini/memories"
|
|
2134
|
+
};
|
|
2135
|
+
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
1363
2136
|
}
|
|
1364
2137
|
function generateGeminiMemoryMarkdown(rule) {
|
|
1365
2138
|
return rule.content.trim();
|
|
@@ -1388,24 +2161,42 @@ function generateGeminiRootMarkdown(rootRule, memoryRules, _baseDir) {
|
|
|
1388
2161
|
}
|
|
1389
2162
|
return lines.join("\n");
|
|
1390
2163
|
}
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
"",
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
2164
|
+
|
|
2165
|
+
// src/generators/rules/junie.ts
|
|
2166
|
+
async function generateJunieConfig(rules, config, baseDir) {
|
|
2167
|
+
const generatorConfig = {
|
|
2168
|
+
tool: "junie",
|
|
2169
|
+
fileExtension: ".md",
|
|
2170
|
+
ignoreFileName: ".aiignore",
|
|
2171
|
+
generateContent: (rule) => rule.content.trim(),
|
|
2172
|
+
generateRootContent: generateGuidelinesMarkdown,
|
|
2173
|
+
rootFilePath: ".junie/guidelines.md"
|
|
2174
|
+
};
|
|
2175
|
+
return generateComplexRules(rules, config, generatorConfig, baseDir);
|
|
2176
|
+
}
|
|
2177
|
+
function generateGuidelinesMarkdown(rootRule, detailRules) {
|
|
2178
|
+
const lines = [];
|
|
2179
|
+
if (rootRule) {
|
|
2180
|
+
lines.push(rootRule.content);
|
|
2181
|
+
lines.push("");
|
|
2182
|
+
}
|
|
2183
|
+
if (detailRules.length > 0) {
|
|
2184
|
+
for (const rule of detailRules) {
|
|
2185
|
+
lines.push(rule.content);
|
|
2186
|
+
lines.push("");
|
|
2187
|
+
}
|
|
2188
|
+
}
|
|
2189
|
+
return lines.join("\n").trim();
|
|
1399
2190
|
}
|
|
1400
2191
|
|
|
1401
2192
|
// src/generators/rules/kiro.ts
|
|
1402
|
-
var
|
|
2193
|
+
var import_node_path10 = require("path");
|
|
1403
2194
|
async function generateKiroConfig(rules, config, baseDir) {
|
|
1404
2195
|
const outputs = [];
|
|
1405
2196
|
for (const rule of rules) {
|
|
1406
2197
|
const content = generateKiroMarkdown(rule);
|
|
1407
|
-
const outputDir = baseDir ? (0,
|
|
1408
|
-
const filepath = (0,
|
|
2198
|
+
const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
|
|
2199
|
+
const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
|
|
1409
2200
|
outputs.push({
|
|
1410
2201
|
tool: "kiro",
|
|
1411
2202
|
filepath,
|
|
@@ -1459,7 +2250,10 @@ async function generateConfigurations(rules, config, targetTools, baseDir) {
|
|
|
1459
2250
|
function filterRulesForTool(rules, tool, config) {
|
|
1460
2251
|
return rules.filter((rule) => {
|
|
1461
2252
|
const targets = resolveTargets(rule.frontmatter.targets, config);
|
|
1462
|
-
|
|
2253
|
+
if (!targets.includes(tool)) {
|
|
2254
|
+
return false;
|
|
2255
|
+
}
|
|
2256
|
+
return isToolSpecificRule(rule, tool);
|
|
1463
2257
|
});
|
|
1464
2258
|
}
|
|
1465
2259
|
async function generateForTool(tool, rules, config, baseDir) {
|
|
@@ -1490,6 +2284,11 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
1490
2284
|
return generateRooConfig(rules, config, baseDir);
|
|
1491
2285
|
case "geminicli":
|
|
1492
2286
|
return generateGeminiConfig(rules, config, baseDir);
|
|
2287
|
+
case "junie": {
|
|
2288
|
+
const junieRulesOutputs = await generateJunieConfig(rules, config, baseDir);
|
|
2289
|
+
const junieIgnoreOutputs = await generateJunieIgnoreFiles(rules, config, baseDir);
|
|
2290
|
+
return [...junieRulesOutputs, ...junieIgnoreOutputs];
|
|
2291
|
+
}
|
|
1493
2292
|
case "kiro": {
|
|
1494
2293
|
const kiroRulesOutputs = await generateKiroConfig(rules, config, baseDir);
|
|
1495
2294
|
const kiroIgnoreOutputs = await generateKiroIgnoreFiles(rules, config, baseDir);
|
|
@@ -1502,83 +2301,8 @@ async function generateForTool(tool, rules, config, baseDir) {
|
|
|
1502
2301
|
}
|
|
1503
2302
|
|
|
1504
2303
|
// src/core/parser.ts
|
|
1505
|
-
var
|
|
2304
|
+
var import_node_path11 = require("path");
|
|
1506
2305
|
var import_gray_matter = __toESM(require("gray-matter"), 1);
|
|
1507
|
-
|
|
1508
|
-
// src/types/config.ts
|
|
1509
|
-
var import_mini3 = require("zod/mini");
|
|
1510
|
-
init_tool_targets();
|
|
1511
|
-
var ConfigSchema = import_mini3.z.object({
|
|
1512
|
-
aiRulesDir: import_mini3.z.string(),
|
|
1513
|
-
outputPaths: import_mini3.z.record(ToolTargetSchema, import_mini3.z.string()),
|
|
1514
|
-
watchEnabled: import_mini3.z.boolean(),
|
|
1515
|
-
defaultTargets: ToolTargetsSchema
|
|
1516
|
-
});
|
|
1517
|
-
|
|
1518
|
-
// src/types/mcp.ts
|
|
1519
|
-
var import_mini4 = require("zod/mini");
|
|
1520
|
-
init_tool_targets();
|
|
1521
|
-
var McpTransportTypeSchema = import_mini4.z.enum(["stdio", "sse", "http"]);
|
|
1522
|
-
var McpServerBaseSchema = import_mini4.z.object({
|
|
1523
|
-
command: import_mini4.z.optional(import_mini4.z.string()),
|
|
1524
|
-
args: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
|
|
1525
|
-
url: import_mini4.z.optional(import_mini4.z.string()),
|
|
1526
|
-
httpUrl: import_mini4.z.optional(import_mini4.z.string()),
|
|
1527
|
-
env: import_mini4.z.optional(import_mini4.z.record(import_mini4.z.string(), import_mini4.z.string())),
|
|
1528
|
-
disabled: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
1529
|
-
networkTimeout: import_mini4.z.optional(import_mini4.z.number()),
|
|
1530
|
-
timeout: import_mini4.z.optional(import_mini4.z.number()),
|
|
1531
|
-
trust: import_mini4.z.optional(import_mini4.z.boolean()),
|
|
1532
|
-
cwd: import_mini4.z.optional(import_mini4.z.string()),
|
|
1533
|
-
transport: import_mini4.z.optional(McpTransportTypeSchema),
|
|
1534
|
-
type: import_mini4.z.optional(import_mini4.z.enum(["sse", "streamable-http"])),
|
|
1535
|
-
alwaysAllow: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
|
|
1536
|
-
tools: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
|
|
1537
|
-
kiroAutoApprove: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
|
|
1538
|
-
kiroAutoBlock: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string()))
|
|
1539
|
-
});
|
|
1540
|
-
var RulesyncMcpServerSchema = import_mini4.z.extend(McpServerBaseSchema, {
|
|
1541
|
-
targets: import_mini4.z.optional(RulesyncTargetsSchema)
|
|
1542
|
-
});
|
|
1543
|
-
var McpConfigSchema = import_mini4.z.object({
|
|
1544
|
-
mcpServers: import_mini4.z.record(import_mini4.z.string(), McpServerBaseSchema)
|
|
1545
|
-
});
|
|
1546
|
-
var RulesyncMcpConfigSchema = import_mini4.z.object({
|
|
1547
|
-
mcpServers: import_mini4.z.record(import_mini4.z.string(), RulesyncMcpServerSchema)
|
|
1548
|
-
});
|
|
1549
|
-
|
|
1550
|
-
// src/types/rules.ts
|
|
1551
|
-
var import_mini5 = require("zod/mini");
|
|
1552
|
-
init_tool_targets();
|
|
1553
|
-
var RuleFrontmatterSchema = import_mini5.z.object({
|
|
1554
|
-
root: import_mini5.z.boolean(),
|
|
1555
|
-
targets: RulesyncTargetsSchema,
|
|
1556
|
-
description: import_mini5.z.string(),
|
|
1557
|
-
globs: import_mini5.z.array(import_mini5.z.string()),
|
|
1558
|
-
cursorRuleType: import_mini5.z.optional(import_mini5.z.enum(["always", "manual", "specificFiles", "intelligently"])),
|
|
1559
|
-
tags: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string()))
|
|
1560
|
-
});
|
|
1561
|
-
var ParsedRuleSchema = import_mini5.z.object({
|
|
1562
|
-
frontmatter: RuleFrontmatterSchema,
|
|
1563
|
-
content: import_mini5.z.string(),
|
|
1564
|
-
filename: import_mini5.z.string(),
|
|
1565
|
-
filepath: import_mini5.z.string()
|
|
1566
|
-
});
|
|
1567
|
-
var GeneratedOutputSchema = import_mini5.z.object({
|
|
1568
|
-
tool: ToolTargetSchema,
|
|
1569
|
-
filepath: import_mini5.z.string(),
|
|
1570
|
-
content: import_mini5.z.string()
|
|
1571
|
-
});
|
|
1572
|
-
var GenerateOptionsSchema = import_mini5.z.object({
|
|
1573
|
-
targetTools: import_mini5.z.optional(ToolTargetsSchema),
|
|
1574
|
-
outputDir: import_mini5.z.optional(import_mini5.z.string()),
|
|
1575
|
-
watch: import_mini5.z.optional(import_mini5.z.boolean())
|
|
1576
|
-
});
|
|
1577
|
-
|
|
1578
|
-
// src/types/index.ts
|
|
1579
|
-
init_tool_targets();
|
|
1580
|
-
|
|
1581
|
-
// src/core/parser.ts
|
|
1582
2306
|
async function parseRulesFromDirectory(aiRulesDir) {
|
|
1583
2307
|
const ignorePatterns = await loadIgnorePatterns();
|
|
1584
2308
|
const allRuleFiles = await findFiles(aiRulesDir, ".md");
|
|
@@ -1615,7 +2339,7 @@ async function parseRuleFile(filepath) {
|
|
|
1615
2339
|
const parsed = (0, import_gray_matter.default)(content);
|
|
1616
2340
|
try {
|
|
1617
2341
|
const frontmatter = RuleFrontmatterSchema.parse(parsed.data);
|
|
1618
|
-
const filename = (0,
|
|
2342
|
+
const filename = (0, import_node_path11.basename)(filepath, ".md");
|
|
1619
2343
|
return {
|
|
1620
2344
|
frontmatter,
|
|
1621
2345
|
content: parsed.content,
|
|
@@ -1680,7 +2404,7 @@ async function validateRule(rule) {
|
|
|
1680
2404
|
}
|
|
1681
2405
|
|
|
1682
2406
|
// src/core/mcp-generator.ts
|
|
1683
|
-
var
|
|
2407
|
+
var path4 = __toESM(require("path"), 1);
|
|
1684
2408
|
|
|
1685
2409
|
// src/generators/mcp/index.ts
|
|
1686
2410
|
init_augmentcode();
|
|
@@ -1689,14 +2413,15 @@ init_cline();
|
|
|
1689
2413
|
init_copilot();
|
|
1690
2414
|
init_cursor();
|
|
1691
2415
|
init_geminicli();
|
|
2416
|
+
init_junie();
|
|
1692
2417
|
init_kiro();
|
|
1693
2418
|
init_roo();
|
|
1694
2419
|
|
|
1695
2420
|
// src/core/mcp-parser.ts
|
|
1696
2421
|
var fs = __toESM(require("fs"), 1);
|
|
1697
|
-
var
|
|
2422
|
+
var path3 = __toESM(require("path"), 1);
|
|
1698
2423
|
function parseMcpConfig(projectRoot) {
|
|
1699
|
-
const mcpPath =
|
|
2424
|
+
const mcpPath = path3.join(projectRoot, ".rulesync", ".mcp.json");
|
|
1700
2425
|
if (!fs.existsSync(mcpPath)) {
|
|
1701
2426
|
return null;
|
|
1702
2427
|
}
|
|
@@ -1720,7 +2445,7 @@ function parseMcpConfig(projectRoot) {
|
|
|
1720
2445
|
}
|
|
1721
2446
|
|
|
1722
2447
|
// src/core/mcp-generator.ts
|
|
1723
|
-
async function generateMcpConfigs(projectRoot, baseDir) {
|
|
2448
|
+
async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
|
|
1724
2449
|
const results = [];
|
|
1725
2450
|
const targetRoot = baseDir || projectRoot;
|
|
1726
2451
|
const config = parseMcpConfig(projectRoot);
|
|
@@ -1730,55 +2455,70 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
1730
2455
|
const generators = [
|
|
1731
2456
|
{
|
|
1732
2457
|
tool: "augmentcode-project",
|
|
1733
|
-
path:
|
|
2458
|
+
path: path4.join(targetRoot, ".mcp.json"),
|
|
1734
2459
|
generate: () => generateAugmentcodeMcp(config)
|
|
1735
2460
|
},
|
|
1736
2461
|
{
|
|
1737
2462
|
tool: "augmentcode-legacy-project",
|
|
1738
|
-
path:
|
|
2463
|
+
path: path4.join(targetRoot, ".mcp.json"),
|
|
1739
2464
|
generate: () => generateAugmentcodeMcp(config)
|
|
1740
2465
|
},
|
|
1741
2466
|
{
|
|
1742
2467
|
tool: "claude-project",
|
|
1743
|
-
path:
|
|
2468
|
+
path: path4.join(targetRoot, ".mcp.json"),
|
|
1744
2469
|
generate: () => generateClaudeMcp(config)
|
|
1745
2470
|
},
|
|
1746
2471
|
{
|
|
1747
2472
|
tool: "copilot-editor",
|
|
1748
|
-
path:
|
|
2473
|
+
path: path4.join(targetRoot, ".vscode", "mcp.json"),
|
|
1749
2474
|
generate: () => generateCopilotMcp(config, "editor")
|
|
1750
2475
|
},
|
|
1751
2476
|
{
|
|
1752
2477
|
tool: "cursor-project",
|
|
1753
|
-
path:
|
|
2478
|
+
path: path4.join(targetRoot, ".cursor", "mcp.json"),
|
|
1754
2479
|
generate: () => generateCursorMcp(config)
|
|
1755
2480
|
},
|
|
1756
2481
|
{
|
|
1757
2482
|
tool: "cline-project",
|
|
1758
|
-
path:
|
|
2483
|
+
path: path4.join(targetRoot, ".cline", "mcp.json"),
|
|
1759
2484
|
generate: () => generateClineMcp(config)
|
|
1760
2485
|
},
|
|
1761
2486
|
{
|
|
1762
2487
|
tool: "gemini-project",
|
|
1763
|
-
path:
|
|
2488
|
+
path: path4.join(targetRoot, ".gemini", "settings.json"),
|
|
1764
2489
|
generate: () => generateGeminiCliMcp(config)
|
|
1765
2490
|
},
|
|
2491
|
+
{
|
|
2492
|
+
tool: "junie-project",
|
|
2493
|
+
path: path4.join(targetRoot, ".junie", "mcp-config.json"),
|
|
2494
|
+
generate: () => generateJunieMcp(config)
|
|
2495
|
+
},
|
|
1766
2496
|
{
|
|
1767
2497
|
tool: "kiro-project",
|
|
1768
|
-
path:
|
|
2498
|
+
path: path4.join(targetRoot, ".kiro", "mcp.json"),
|
|
1769
2499
|
generate: () => generateKiroMcp(config)
|
|
1770
2500
|
},
|
|
1771
2501
|
{
|
|
1772
2502
|
tool: "roo-project",
|
|
1773
|
-
path:
|
|
2503
|
+
path: path4.join(targetRoot, ".roo", "mcp.json"),
|
|
1774
2504
|
generate: () => generateRooMcp(config)
|
|
1775
2505
|
}
|
|
1776
2506
|
];
|
|
1777
|
-
|
|
2507
|
+
const filteredGenerators = targetTools ? generators.filter((g) => {
|
|
2508
|
+
const baseTool = g.tool.split("-")[0];
|
|
2509
|
+
if (!isToolTarget(baseTool)) {
|
|
2510
|
+
return false;
|
|
2511
|
+
}
|
|
2512
|
+
if (baseTool === "augmentcode") {
|
|
2513
|
+
return targetTools.includes("augmentcode") || targetTools.includes("augmentcode-legacy");
|
|
2514
|
+
}
|
|
2515
|
+
return targetTools.includes(baseTool);
|
|
2516
|
+
}) : generators;
|
|
2517
|
+
for (const generator of filteredGenerators) {
|
|
1778
2518
|
try {
|
|
1779
2519
|
const content = generator.generate();
|
|
1780
2520
|
const parsed = JSON.parse(content);
|
|
1781
|
-
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
2521
|
+
if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
|
|
1782
2522
|
if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
|
|
1783
2523
|
results.push({
|
|
1784
2524
|
tool: generator.tool,
|
|
@@ -1818,15 +2558,58 @@ async function generateMcpConfigs(projectRoot, baseDir) {
|
|
|
1818
2558
|
|
|
1819
2559
|
// src/cli/commands/generate.ts
|
|
1820
2560
|
async function generateCommand(options = {}) {
|
|
1821
|
-
const
|
|
1822
|
-
|
|
2561
|
+
const configLoaderOptions = {
|
|
2562
|
+
...options.config !== void 0 && { configPath: options.config },
|
|
2563
|
+
...options.noConfig !== void 0 && { noConfig: options.noConfig }
|
|
2564
|
+
};
|
|
2565
|
+
const configResult = await loadConfig(configLoaderOptions);
|
|
2566
|
+
const cliOptions = {
|
|
2567
|
+
...options.tools !== void 0 && { tools: options.tools },
|
|
2568
|
+
...options.verbose !== void 0 && { verbose: options.verbose },
|
|
2569
|
+
...options.delete !== void 0 && { delete: options.delete },
|
|
2570
|
+
...options.baseDirs !== void 0 && { baseDirs: options.baseDirs }
|
|
2571
|
+
};
|
|
2572
|
+
const config = mergeWithCliOptions(configResult.config, cliOptions);
|
|
2573
|
+
if (options.tools && options.tools.length > 0) {
|
|
2574
|
+
const configTargets = config.defaultTargets;
|
|
2575
|
+
const cliTools = options.tools;
|
|
2576
|
+
const cliToolsSet = new Set(cliTools);
|
|
2577
|
+
const configTargetsSet = new Set(configTargets);
|
|
2578
|
+
const notInConfig = cliTools.filter((tool) => !configTargetsSet.has(tool));
|
|
2579
|
+
const notInCli = configTargets.filter((tool) => !cliToolsSet.has(tool));
|
|
2580
|
+
if (notInConfig.length > 0 || notInCli.length > 0) {
|
|
2581
|
+
console.warn("\u26A0\uFE0F Warning: CLI tool selection differs from configuration!");
|
|
2582
|
+
console.warn(` Config targets: ${configTargets.join(", ")}`);
|
|
2583
|
+
console.warn(` CLI specified: ${cliTools.join(", ")}`);
|
|
2584
|
+
if (notInConfig.length > 0) {
|
|
2585
|
+
console.warn(` Tools specified but not in config: ${notInConfig.join(", ")}`);
|
|
2586
|
+
}
|
|
2587
|
+
if (notInCli.length > 0) {
|
|
2588
|
+
console.warn(` Tools in config but not specified: ${notInCli.join(", ")}`);
|
|
2589
|
+
}
|
|
2590
|
+
console.warn("\n The configuration file targets will be used.");
|
|
2591
|
+
console.warn(" To change targets, update your rulesync config file.");
|
|
2592
|
+
console.warn("");
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
let baseDirs;
|
|
2596
|
+
if (config.baseDir) {
|
|
2597
|
+
baseDirs = Array.isArray(config.baseDir) ? config.baseDir : [config.baseDir];
|
|
2598
|
+
} else if (options.baseDirs) {
|
|
2599
|
+
baseDirs = options.baseDirs;
|
|
2600
|
+
} else {
|
|
2601
|
+
baseDirs = [process.cwd()];
|
|
2602
|
+
}
|
|
2603
|
+
if (config.verbose && configResult.filepath) {
|
|
2604
|
+
console.log(`Loaded configuration from: ${configResult.filepath}`);
|
|
2605
|
+
}
|
|
1823
2606
|
console.log("Generating configuration files...");
|
|
1824
2607
|
if (!await fileExists(config.aiRulesDir)) {
|
|
1825
2608
|
console.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
1826
2609
|
process.exit(1);
|
|
1827
2610
|
}
|
|
1828
2611
|
try {
|
|
1829
|
-
if (
|
|
2612
|
+
if (config.verbose) {
|
|
1830
2613
|
console.log(`Parsing rules from ${config.aiRulesDir}...`);
|
|
1831
2614
|
}
|
|
1832
2615
|
const rules = await parseRulesFromDirectory(config.aiRulesDir);
|
|
@@ -1834,18 +2617,26 @@ async function generateCommand(options = {}) {
|
|
|
1834
2617
|
console.warn("\u26A0\uFE0F No rules found in .rulesync directory");
|
|
1835
2618
|
return;
|
|
1836
2619
|
}
|
|
1837
|
-
if (
|
|
2620
|
+
if (config.verbose) {
|
|
1838
2621
|
console.log(`Found ${rules.length} rule(s)`);
|
|
1839
2622
|
console.log(`Base directories: ${baseDirs.join(", ")}`);
|
|
1840
2623
|
}
|
|
1841
|
-
if (
|
|
1842
|
-
if (
|
|
2624
|
+
if (config.delete) {
|
|
2625
|
+
if (config.verbose) {
|
|
1843
2626
|
console.log("Deleting existing output directories...");
|
|
1844
2627
|
}
|
|
1845
|
-
const targetTools =
|
|
2628
|
+
const targetTools = config.defaultTargets;
|
|
1846
2629
|
const deleteTasks = [];
|
|
1847
2630
|
for (const tool of targetTools) {
|
|
1848
2631
|
switch (tool) {
|
|
2632
|
+
case "augmentcode":
|
|
2633
|
+
deleteTasks.push(removeDirectory((0, import_node_path12.join)(".augment", "rules")));
|
|
2634
|
+
deleteTasks.push(removeDirectory((0, import_node_path12.join)(".augment", "ignore")));
|
|
2635
|
+
break;
|
|
2636
|
+
case "augmentcode-legacy":
|
|
2637
|
+
deleteTasks.push(removeClaudeGeneratedFiles());
|
|
2638
|
+
deleteTasks.push(removeDirectory((0, import_node_path12.join)(".augment", "ignore")));
|
|
2639
|
+
break;
|
|
1849
2640
|
case "copilot":
|
|
1850
2641
|
deleteTasks.push(removeDirectory(config.outputPaths.copilot));
|
|
1851
2642
|
break;
|
|
@@ -1870,19 +2661,19 @@ async function generateCommand(options = {}) {
|
|
|
1870
2661
|
}
|
|
1871
2662
|
}
|
|
1872
2663
|
await Promise.all(deleteTasks);
|
|
1873
|
-
if (
|
|
2664
|
+
if (config.verbose) {
|
|
1874
2665
|
console.log("Deleted existing output directories");
|
|
1875
2666
|
}
|
|
1876
2667
|
}
|
|
1877
2668
|
let totalOutputs = 0;
|
|
1878
2669
|
for (const baseDir of baseDirs) {
|
|
1879
|
-
if (
|
|
2670
|
+
if (config.verbose) {
|
|
1880
2671
|
console.log(`
|
|
1881
2672
|
Generating configurations for base directory: ${baseDir}`);
|
|
1882
2673
|
}
|
|
1883
|
-
const outputs = await generateConfigurations(rules, config,
|
|
2674
|
+
const outputs = await generateConfigurations(rules, config, config.defaultTargets, baseDir);
|
|
1884
2675
|
if (outputs.length === 0) {
|
|
1885
|
-
if (
|
|
2676
|
+
if (config.verbose) {
|
|
1886
2677
|
console.warn(`\u26A0\uFE0F No configurations generated for ${baseDir}`);
|
|
1887
2678
|
}
|
|
1888
2679
|
continue;
|
|
@@ -1897,17 +2688,18 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1897
2688
|
console.warn("\u26A0\uFE0F No configurations generated");
|
|
1898
2689
|
return;
|
|
1899
2690
|
}
|
|
1900
|
-
if (
|
|
2691
|
+
if (config.verbose) {
|
|
1901
2692
|
console.log("\nGenerating MCP configurations...");
|
|
1902
2693
|
}
|
|
1903
2694
|
let totalMcpOutputs = 0;
|
|
1904
2695
|
for (const baseDir of baseDirs) {
|
|
1905
2696
|
const mcpResults = await generateMcpConfigs(
|
|
1906
2697
|
process.cwd(),
|
|
1907
|
-
baseDir === process.cwd() ? void 0 : baseDir
|
|
2698
|
+
baseDir === process.cwd() ? void 0 : baseDir,
|
|
2699
|
+
config.defaultTargets
|
|
1908
2700
|
);
|
|
1909
2701
|
if (mcpResults.length === 0) {
|
|
1910
|
-
if (
|
|
2702
|
+
if (config.verbose) {
|
|
1911
2703
|
console.log(`No MCP configuration found for ${baseDir}`);
|
|
1912
2704
|
}
|
|
1913
2705
|
continue;
|
|
@@ -1918,7 +2710,7 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1918
2710
|
totalMcpOutputs++;
|
|
1919
2711
|
} else if (result.status === "error") {
|
|
1920
2712
|
console.error(`\u274C Failed to generate ${result.tool} MCP configuration: ${result.error}`);
|
|
1921
|
-
} else if (
|
|
2713
|
+
} else if (config.verbose && result.status === "skipped") {
|
|
1922
2714
|
console.log(`\u23ED\uFE0F Skipped ${result.tool} MCP configuration (no servers configured)`);
|
|
1923
2715
|
}
|
|
1924
2716
|
}
|
|
@@ -1937,7 +2729,7 @@ Generating configurations for base directory: ${baseDir}`);
|
|
|
1937
2729
|
}
|
|
1938
2730
|
|
|
1939
2731
|
// src/cli/commands/gitignore.ts
|
|
1940
|
-
var
|
|
2732
|
+
var import_node_fs2 = require("fs");
|
|
1941
2733
|
var import_node_path13 = require("path");
|
|
1942
2734
|
var gitignoreCommand = async () => {
|
|
1943
2735
|
const gitignorePath = (0, import_node_path13.join)(process.cwd(), ".gitignore");
|
|
@@ -1962,6 +2754,8 @@ var gitignoreCommand = async () => {
|
|
|
1962
2754
|
"**/.kiro/steering/",
|
|
1963
2755
|
"**/.augment/rules/",
|
|
1964
2756
|
"**/.augment-guidelines",
|
|
2757
|
+
"**/.junie/guidelines.md",
|
|
2758
|
+
"**/.noai",
|
|
1965
2759
|
"**/.mcp.json",
|
|
1966
2760
|
"!.rulesync/.mcp.json",
|
|
1967
2761
|
"**/.cursor/mcp.json",
|
|
@@ -1971,8 +2765,8 @@ var gitignoreCommand = async () => {
|
|
|
1971
2765
|
"**/.roo/mcp.json"
|
|
1972
2766
|
];
|
|
1973
2767
|
let gitignoreContent = "";
|
|
1974
|
-
if ((0,
|
|
1975
|
-
gitignoreContent = (0,
|
|
2768
|
+
if ((0, import_node_fs2.existsSync)(gitignorePath)) {
|
|
2769
|
+
gitignoreContent = (0, import_node_fs2.readFileSync)(gitignorePath, "utf-8");
|
|
1976
2770
|
}
|
|
1977
2771
|
const linesToAdd = [];
|
|
1978
2772
|
for (const rule of rulesFilesToIgnore) {
|
|
@@ -1989,7 +2783,7 @@ var gitignoreCommand = async () => {
|
|
|
1989
2783
|
${linesToAdd.join("\n")}
|
|
1990
2784
|
` : `${linesToAdd.join("\n")}
|
|
1991
2785
|
`;
|
|
1992
|
-
(0,
|
|
2786
|
+
(0, import_node_fs2.writeFileSync)(gitignorePath, newContent);
|
|
1993
2787
|
console.log(`\u2705 Added ${linesToAdd.length} rules to .gitignore:`);
|
|
1994
2788
|
for (const line of linesToAdd) {
|
|
1995
2789
|
if (!line.startsWith("#")) {
|
|
@@ -1999,7 +2793,7 @@ ${linesToAdd.join("\n")}
|
|
|
1999
2793
|
};
|
|
2000
2794
|
|
|
2001
2795
|
// src/core/importer.ts
|
|
2002
|
-
var
|
|
2796
|
+
var import_node_path19 = require("path");
|
|
2003
2797
|
var import_gray_matter5 = __toESM(require("gray-matter"), 1);
|
|
2004
2798
|
|
|
2005
2799
|
// src/parsers/augmentcode.ts
|
|
@@ -2448,7 +3242,7 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
|
|
|
2448
3242
|
var import_node_path17 = require("path");
|
|
2449
3243
|
var import_gray_matter4 = __toESM(require("gray-matter"), 1);
|
|
2450
3244
|
var import_js_yaml = require("js-yaml");
|
|
2451
|
-
var
|
|
3245
|
+
var import_mini7 = require("zod/mini");
|
|
2452
3246
|
var customMatterOptions = {
|
|
2453
3247
|
engines: {
|
|
2454
3248
|
yaml: {
|
|
@@ -2476,7 +3270,7 @@ var customMatterOptions = {
|
|
|
2476
3270
|
}
|
|
2477
3271
|
};
|
|
2478
3272
|
function convertCursorMdcFrontmatter(cursorFrontmatter, _filename) {
|
|
2479
|
-
const FrontmatterSchema =
|
|
3273
|
+
const FrontmatterSchema = import_mini7.z.record(import_mini7.z.string(), import_mini7.z.unknown());
|
|
2480
3274
|
const parseResult = FrontmatterSchema.safeParse(cursorFrontmatter);
|
|
2481
3275
|
if (!parseResult.success) {
|
|
2482
3276
|
return {
|
|
@@ -2688,6 +3482,42 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
|
|
|
2688
3482
|
});
|
|
2689
3483
|
}
|
|
2690
3484
|
|
|
3485
|
+
// src/parsers/junie.ts
|
|
3486
|
+
var import_node_path18 = require("path");
|
|
3487
|
+
async function parseJunieConfiguration(baseDir = process.cwd()) {
|
|
3488
|
+
const errors = [];
|
|
3489
|
+
const rules = [];
|
|
3490
|
+
const guidelinesPath = (0, import_node_path18.join)(baseDir, ".junie", "guidelines.md");
|
|
3491
|
+
if (!await fileExists(guidelinesPath)) {
|
|
3492
|
+
errors.push(".junie/guidelines.md file not found");
|
|
3493
|
+
return { rules, errors };
|
|
3494
|
+
}
|
|
3495
|
+
try {
|
|
3496
|
+
const content = await readFileContent(guidelinesPath);
|
|
3497
|
+
if (content.trim()) {
|
|
3498
|
+
const frontmatter = {
|
|
3499
|
+
root: false,
|
|
3500
|
+
targets: ["junie"],
|
|
3501
|
+
description: "Junie project guidelines",
|
|
3502
|
+
globs: ["**/*"]
|
|
3503
|
+
};
|
|
3504
|
+
rules.push({
|
|
3505
|
+
frontmatter,
|
|
3506
|
+
content: content.trim(),
|
|
3507
|
+
filename: "junie-guidelines",
|
|
3508
|
+
filepath: guidelinesPath
|
|
3509
|
+
});
|
|
3510
|
+
}
|
|
3511
|
+
} catch (error) {
|
|
3512
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3513
|
+
errors.push(`Failed to parse .junie/guidelines.md: ${errorMessage}`);
|
|
3514
|
+
}
|
|
3515
|
+
if (rules.length === 0) {
|
|
3516
|
+
errors.push("No valid Junie configuration found");
|
|
3517
|
+
}
|
|
3518
|
+
return { rules, errors };
|
|
3519
|
+
}
|
|
3520
|
+
|
|
2691
3521
|
// src/parsers/roo.ts
|
|
2692
3522
|
async function parseRooConfiguration(baseDir = process.cwd()) {
|
|
2693
3523
|
return parseConfigurationFiles(baseDir, {
|
|
@@ -2774,6 +3604,12 @@ async function importConfiguration(options) {
|
|
|
2774
3604
|
mcpServers = geminiResult.mcpServers;
|
|
2775
3605
|
break;
|
|
2776
3606
|
}
|
|
3607
|
+
case "junie": {
|
|
3608
|
+
const junieResult = await parseJunieConfiguration(baseDir);
|
|
3609
|
+
rules = junieResult.rules;
|
|
3610
|
+
errors.push(...junieResult.errors);
|
|
3611
|
+
break;
|
|
3612
|
+
}
|
|
2777
3613
|
default:
|
|
2778
3614
|
errors.push(`Unsupported tool: ${tool}`);
|
|
2779
3615
|
return { success: false, rulesCreated: 0, errors };
|
|
@@ -2786,7 +3622,7 @@ async function importConfiguration(options) {
|
|
|
2786
3622
|
if (rules.length === 0 && !ignorePatterns && !mcpServers) {
|
|
2787
3623
|
return { success: false, rulesCreated: 0, errors };
|
|
2788
3624
|
}
|
|
2789
|
-
const rulesDirPath = (0,
|
|
3625
|
+
const rulesDirPath = (0, import_node_path19.join)(baseDir, rulesDir);
|
|
2790
3626
|
try {
|
|
2791
3627
|
const { mkdir: mkdir3 } = await import("fs/promises");
|
|
2792
3628
|
await mkdir3(rulesDirPath, { recursive: true });
|
|
@@ -2798,9 +3634,9 @@ async function importConfiguration(options) {
|
|
|
2798
3634
|
let rulesCreated = 0;
|
|
2799
3635
|
for (const rule of rules) {
|
|
2800
3636
|
try {
|
|
2801
|
-
const baseFilename =
|
|
3637
|
+
const baseFilename = rule.filename;
|
|
2802
3638
|
const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
|
|
2803
|
-
const filePath = (0,
|
|
3639
|
+
const filePath = (0, import_node_path19.join)(rulesDirPath, `${filename}.md`);
|
|
2804
3640
|
const content = generateRuleFileContent(rule);
|
|
2805
3641
|
await writeFileContent(filePath, content);
|
|
2806
3642
|
rulesCreated++;
|
|
@@ -2815,7 +3651,7 @@ async function importConfiguration(options) {
|
|
|
2815
3651
|
let ignoreFileCreated = false;
|
|
2816
3652
|
if (ignorePatterns && ignorePatterns.length > 0) {
|
|
2817
3653
|
try {
|
|
2818
|
-
const rulesyncignorePath = (0,
|
|
3654
|
+
const rulesyncignorePath = (0, import_node_path19.join)(baseDir, ".rulesyncignore");
|
|
2819
3655
|
const ignoreContent = `${ignorePatterns.join("\n")}
|
|
2820
3656
|
`;
|
|
2821
3657
|
await writeFileContent(rulesyncignorePath, ignoreContent);
|
|
@@ -2831,7 +3667,7 @@ async function importConfiguration(options) {
|
|
|
2831
3667
|
let mcpFileCreated = false;
|
|
2832
3668
|
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
2833
3669
|
try {
|
|
2834
|
-
const mcpPath = (0,
|
|
3670
|
+
const mcpPath = (0, import_node_path19.join)(baseDir, rulesDir, ".mcp.json");
|
|
2835
3671
|
const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
|
|
2836
3672
|
`;
|
|
2837
3673
|
await writeFileContent(mcpPath, mcpContent);
|
|
@@ -2859,7 +3695,7 @@ function generateRuleFileContent(rule) {
|
|
|
2859
3695
|
async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
2860
3696
|
let filename = baseFilename;
|
|
2861
3697
|
let counter = 1;
|
|
2862
|
-
while (await fileExists((0,
|
|
3698
|
+
while (await fileExists((0, import_node_path19.join)(rulesDir, `${filename}.md`))) {
|
|
2863
3699
|
filename = `${baseFilename}-${counter}`;
|
|
2864
3700
|
counter++;
|
|
2865
3701
|
}
|
|
@@ -2870,7 +3706,7 @@ async function generateUniqueFilename(rulesDir, baseFilename) {
|
|
|
2870
3706
|
async function importCommand(options = {}) {
|
|
2871
3707
|
const tools = [];
|
|
2872
3708
|
if (options.augmentcode) tools.push("augmentcode");
|
|
2873
|
-
if (options
|
|
3709
|
+
if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
|
|
2874
3710
|
if (options.claudecode) tools.push("claudecode");
|
|
2875
3711
|
if (options.cursor) tools.push("cursor");
|
|
2876
3712
|
if (options.copilot) tools.push("copilot");
|
|
@@ -2879,7 +3715,7 @@ async function importCommand(options = {}) {
|
|
|
2879
3715
|
if (options.geminicli) tools.push("geminicli");
|
|
2880
3716
|
if (tools.length === 0) {
|
|
2881
3717
|
console.error(
|
|
2882
|
-
"\u274C Please specify one tool to import from (--augmentcode, --
|
|
3718
|
+
"\u274C Please specify one tool to import from (--augmentcode, --augmentcode-legacy, --claudecode, --cursor, --copilot, --cline, --roo, --geminicli)"
|
|
2883
3719
|
);
|
|
2884
3720
|
process.exit(1);
|
|
2885
3721
|
}
|
|
@@ -2926,7 +3762,7 @@ async function importCommand(options = {}) {
|
|
|
2926
3762
|
}
|
|
2927
3763
|
|
|
2928
3764
|
// src/cli/commands/init.ts
|
|
2929
|
-
var
|
|
3765
|
+
var import_node_path20 = require("path");
|
|
2930
3766
|
async function initCommand() {
|
|
2931
3767
|
const aiRulesDir = ".rulesync";
|
|
2932
3768
|
console.log("Initializing rulesync...");
|
|
@@ -2973,7 +3809,7 @@ globs: ["**/*"]
|
|
|
2973
3809
|
- Follow single responsibility principle
|
|
2974
3810
|
`
|
|
2975
3811
|
};
|
|
2976
|
-
const filepath = (0,
|
|
3812
|
+
const filepath = (0, import_node_path20.join)(aiRulesDir, sampleFile.filename);
|
|
2977
3813
|
if (!await fileExists(filepath)) {
|
|
2978
3814
|
await writeFileContent(filepath, sampleFile.content);
|
|
2979
3815
|
console.log(`Created ${filepath}`);
|
|
@@ -3087,11 +3923,11 @@ async function watchCommand() {
|
|
|
3087
3923
|
persistent: true
|
|
3088
3924
|
});
|
|
3089
3925
|
let isGenerating = false;
|
|
3090
|
-
const handleChange = async (
|
|
3926
|
+
const handleChange = async (path5) => {
|
|
3091
3927
|
if (isGenerating) return;
|
|
3092
3928
|
isGenerating = true;
|
|
3093
3929
|
console.log(`
|
|
3094
|
-
\u{1F4DD} Detected change in ${
|
|
3930
|
+
\u{1F4DD} Detected change in ${path5}`);
|
|
3095
3931
|
try {
|
|
3096
3932
|
await generateCommand({ verbose: false });
|
|
3097
3933
|
console.log("\u2705 Regenerated configuration files");
|
|
@@ -3101,10 +3937,10 @@ async function watchCommand() {
|
|
|
3101
3937
|
isGenerating = false;
|
|
3102
3938
|
}
|
|
3103
3939
|
};
|
|
3104
|
-
watcher.on("change", handleChange).on("add", handleChange).on("unlink", (
|
|
3940
|
+
watcher.on("change", handleChange).on("add", handleChange).on("unlink", (path5) => {
|
|
3105
3941
|
console.log(`
|
|
3106
|
-
\u{1F5D1}\uFE0F Removed ${
|
|
3107
|
-
handleChange(
|
|
3942
|
+
\u{1F5D1}\uFE0F Removed ${path5}`);
|
|
3943
|
+
handleChange(path5);
|
|
3108
3944
|
}).on("error", (error) => {
|
|
3109
3945
|
console.error("\u274C Watcher error:", error);
|
|
3110
3946
|
});
|
|
@@ -3117,28 +3953,31 @@ async function watchCommand() {
|
|
|
3117
3953
|
|
|
3118
3954
|
// src/cli/index.ts
|
|
3119
3955
|
var program = new import_commander.Command();
|
|
3120
|
-
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.
|
|
3956
|
+
program.name("rulesync").description("Unified AI rules management CLI tool").version("0.52.0");
|
|
3121
3957
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
3122
3958
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
3123
3959
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|
|
3124
|
-
program.command("import").description("Import configurations from AI tools to rulesync format").option("--augmentcode", "Import from AugmentCode (.augment/rules/)").option("--
|
|
3125
|
-
program.command("generate").description("Generate configuration files for AI tools").option("--augmentcode", "Generate only for AugmentCode").option("--
|
|
3960
|
+
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("-v, --verbose", "Verbose output").action(importCommand);
|
|
3961
|
+
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("--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("--delete", "Delete all existing files in output directories before generating").option(
|
|
3126
3962
|
"-b, --base-dir <paths>",
|
|
3127
3963
|
"Base directories to generate files (comma-separated for multiple paths)"
|
|
3128
|
-
).option("-v, --verbose", "Verbose output").action(async (options) => {
|
|
3964
|
+
).option("-v, --verbose", "Verbose output").option("-c, --config <path>", "Path to configuration file").option("--no-config", "Disable configuration file loading").action(async (options) => {
|
|
3129
3965
|
const tools = [];
|
|
3130
3966
|
if (options.augmentcode) tools.push("augmentcode");
|
|
3131
|
-
if (options
|
|
3967
|
+
if (options["augmentcode-legacy"]) tools.push("augmentcode-legacy");
|
|
3132
3968
|
if (options.copilot) tools.push("copilot");
|
|
3133
3969
|
if (options.cursor) tools.push("cursor");
|
|
3134
3970
|
if (options.cline) tools.push("cline");
|
|
3135
3971
|
if (options.claudecode) tools.push("claudecode");
|
|
3136
3972
|
if (options.roo) tools.push("roo");
|
|
3137
3973
|
if (options.geminicli) tools.push("geminicli");
|
|
3974
|
+
if (options.junie) tools.push("junie");
|
|
3138
3975
|
if (options.kiro) tools.push("kiro");
|
|
3139
3976
|
const generateOptions = {
|
|
3140
3977
|
verbose: options.verbose,
|
|
3141
|
-
delete: options.delete
|
|
3978
|
+
delete: options.delete,
|
|
3979
|
+
config: options.config,
|
|
3980
|
+
noConfig: options.noConfig
|
|
3142
3981
|
};
|
|
3143
3982
|
if (tools.length > 0) {
|
|
3144
3983
|
generateOptions.tools = tools;
|
|
@@ -3151,4 +3990,5 @@ program.command("generate").description("Generate configuration files for AI too
|
|
|
3151
3990
|
program.command("validate").description("Validate rulesync configuration").action(validateCommand);
|
|
3152
3991
|
program.command("status").description("Show current status of rulesync").action(statusCommand);
|
|
3153
3992
|
program.command("watch").description("Watch for changes and auto-generate configurations").action(watchCommand);
|
|
3993
|
+
program.command("config").description("Show or initialize rulesync configuration").option("--init", "Initialize a new configuration file").option("--format <format>", "Configuration file format (jsonc, ts)", "jsonc").option("--targets <tools>", "Comma-separated list of tools to generate for").option("--exclude <tools>", "Comma-separated list of tools to exclude").option("--ai-rules-dir <dir>", "Directory containing AI rule files").option("--base-dir <path>", "Base directory for generation").option("--verbose", "Enable verbose output").option("--delete", "Delete existing files before generating").action(configCommand);
|
|
3154
3994
|
program.parse();
|