rulesync 0.45.0 → 0.48.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/dist/index.cjs CHANGED
@@ -27,22 +27,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
 
29
29
  // src/types/tool-targets.ts
30
- var import_v4_mini, ToolTargetSchema, ToolTargetsSchema, WildcardTargetSchema, RulesyncTargetsSchema;
30
+ var import_mini, ToolTargetSchema, ToolTargetsSchema, WildcardTargetSchema, RulesyncTargetsSchema;
31
31
  var init_tool_targets = __esm({
32
32
  "src/types/tool-targets.ts"() {
33
33
  "use strict";
34
- import_v4_mini = require("zod/v4-mini");
35
- ToolTargetSchema = import_v4_mini.z.enum([
34
+ import_mini = require("zod/mini");
35
+ ToolTargetSchema = import_mini.z.enum([
36
36
  "copilot",
37
37
  "cursor",
38
38
  "cline",
39
39
  "claudecode",
40
40
  "roo",
41
- "geminicli"
41
+ "geminicli",
42
+ "kiro"
42
43
  ]);
43
- ToolTargetsSchema = import_v4_mini.z.array(ToolTargetSchema);
44
- WildcardTargetSchema = import_v4_mini.z.tuple([import_v4_mini.z.literal("*")]);
45
- RulesyncTargetsSchema = import_v4_mini.z.union([ToolTargetsSchema, WildcardTargetSchema]);
44
+ ToolTargetsSchema = import_mini.z.array(ToolTargetSchema);
45
+ WildcardTargetSchema = import_mini.z.tuple([import_mini.z.literal("*")]);
46
+ RulesyncTargetsSchema = import_mini.z.union([ToolTargetsSchema, WildcardTargetSchema]);
46
47
  }
47
48
  });
48
49
 
@@ -294,6 +295,57 @@ var init_geminicli = __esm({
294
295
  }
295
296
  });
296
297
 
298
+ // src/generators/mcp/kiro.ts
299
+ function generateKiroMcp(config) {
300
+ const kiroConfig = {
301
+ mcpServers: {}
302
+ };
303
+ for (const [serverName, server] of Object.entries(config.mcpServers)) {
304
+ if (!shouldIncludeServer(server, "kiro")) continue;
305
+ const kiroServer = {};
306
+ if (server.command) {
307
+ kiroServer.command = server.command;
308
+ if (server.args) kiroServer.args = server.args;
309
+ } else if (server.url || server.httpUrl) {
310
+ const url = server.httpUrl || server.url;
311
+ if (url) {
312
+ kiroServer.url = url;
313
+ }
314
+ if (server.httpUrl || server.transport === "http") {
315
+ kiroServer.transport = "streamable-http";
316
+ } else if (server.transport === "sse" || server.type === "sse") {
317
+ kiroServer.transport = "sse";
318
+ }
319
+ }
320
+ if (server.env) {
321
+ kiroServer.env = server.env;
322
+ }
323
+ if (server.timeout) {
324
+ kiroServer.timeout = server.timeout;
325
+ }
326
+ if (server.disabled !== void 0) {
327
+ kiroServer.disabled = server.disabled;
328
+ }
329
+ if (server.transport) {
330
+ kiroServer.transport = server.transport;
331
+ }
332
+ if (server.kiroAutoApprove) {
333
+ kiroServer.autoApprove = server.kiroAutoApprove;
334
+ }
335
+ if (server.kiroAutoBlock) {
336
+ kiroServer.autoBlock = server.kiroAutoBlock;
337
+ }
338
+ kiroConfig.mcpServers[serverName] = kiroServer;
339
+ }
340
+ return JSON.stringify(kiroConfig, null, 2);
341
+ }
342
+ var init_kiro = __esm({
343
+ "src/generators/mcp/kiro.ts"() {
344
+ "use strict";
345
+ init_mcp_helpers();
346
+ }
347
+ });
348
+
297
349
  // src/generators/mcp/roo.ts
298
350
  function generateRooMcp(config) {
299
351
  const rooConfig = {
@@ -364,10 +416,11 @@ function getDefaultConfig() {
364
416
  cline: ".clinerules",
365
417
  claudecode: ".",
366
418
  roo: ".roo/rules",
367
- geminicli: ".gemini/memories"
419
+ geminicli: ".gemini/memories",
420
+ kiro: ".kiro/steering"
368
421
  },
369
422
  watchEnabled: false,
370
- defaultTargets: ["copilot", "cursor", "cline", "claudecode", "roo", "geminicli"]
423
+ defaultTargets: ["copilot", "cursor", "cline", "claudecode", "roo", "geminicli", "kiro"]
371
424
  };
372
425
  }
373
426
  function resolveTargets(targets, config) {
@@ -414,27 +467,138 @@ async function addCommand(filename) {
414
467
  }
415
468
  }
416
469
 
470
+ // src/generators/ignore/kiro.ts
471
+ var import_node_path = require("path");
472
+ async function generateKiroIgnoreFiles(rules, config, baseDir) {
473
+ const outputs = [];
474
+ const aiignoreContent = generateAiignoreContent(rules);
475
+ const outputPath = baseDir || process.cwd();
476
+ const filepath = (0, import_node_path.join)(outputPath, ".aiignore");
477
+ outputs.push({
478
+ tool: "kiro",
479
+ filepath,
480
+ content: aiignoreContent
481
+ });
482
+ return outputs;
483
+ }
484
+ function generateAiignoreContent(rules) {
485
+ const lines = [
486
+ "# Generated by rulesync - Kiro AI-specific exclusions",
487
+ "# This file excludes files that can be in Git but shouldn't be read by the AI",
488
+ ""
489
+ ];
490
+ lines.push(
491
+ "# Data files AI shouldn't process",
492
+ "*.csv",
493
+ "*.tsv",
494
+ "*.sqlite",
495
+ "*.db",
496
+ "",
497
+ "# Large binary files",
498
+ "*.zip",
499
+ "*.tar.gz",
500
+ "*.rar",
501
+ "",
502
+ "# Sensitive documentation",
503
+ "internal-docs/",
504
+ "confidential/",
505
+ "",
506
+ "# Test data that might confuse AI",
507
+ "test/fixtures/large-*.json",
508
+ "benchmark-results/",
509
+ "",
510
+ "# Reinforce critical exclusions from .gitignore",
511
+ "*.pem",
512
+ "*.key",
513
+ ".env*",
514
+ ""
515
+ );
516
+ const rulePatterns = extractIgnorePatternsFromRules(rules);
517
+ if (rulePatterns.length > 0) {
518
+ lines.push("# Project-specific exclusions from rulesync rules");
519
+ lines.push(...rulePatterns);
520
+ lines.push("");
521
+ }
522
+ return lines.join("\n");
523
+ }
524
+ function extractIgnorePatternsFromRules(rules) {
525
+ const patterns = [];
526
+ for (const rule of rules) {
527
+ if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
528
+ for (const glob of rule.frontmatter.globs) {
529
+ if (shouldExcludeFromAI(glob)) {
530
+ patterns.push(`# Exclude: ${rule.frontmatter.description}`);
531
+ patterns.push(glob);
532
+ }
533
+ }
534
+ }
535
+ const contentPatterns = extractIgnorePatternsFromContent(rule.content);
536
+ patterns.push(...contentPatterns);
537
+ }
538
+ return patterns;
539
+ }
540
+ function shouldExcludeFromAI(glob) {
541
+ const excludePatterns = [
542
+ // Test and fixture files that might be large or confusing
543
+ "**/test/fixtures/**",
544
+ "**/tests/fixtures/**",
545
+ "**/*.fixture.*",
546
+ // Build and generated files
547
+ "**/dist/**",
548
+ "**/build/**",
549
+ "**/coverage/**",
550
+ // Configuration that might contain sensitive data
551
+ "**/config/production/**",
552
+ "**/config/prod/**",
553
+ "**/*.prod.*",
554
+ // Documentation that might be sensitive
555
+ "**/internal/**",
556
+ "**/private/**",
557
+ "**/confidential/**"
558
+ ];
559
+ return excludePatterns.some((pattern) => {
560
+ const regex = new RegExp(pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*"));
561
+ return regex.test(glob);
562
+ });
563
+ }
564
+ function extractIgnorePatternsFromContent(content) {
565
+ const patterns = [];
566
+ const lines = content.split("\n");
567
+ for (const line of lines) {
568
+ const trimmed = line.trim();
569
+ if (trimmed.startsWith("# IGNORE:") || trimmed.startsWith("# aiignore:")) {
570
+ const pattern = trimmed.replace(/^# (IGNORE|aiignore):\s*/, "").trim();
571
+ if (pattern) {
572
+ patterns.push(pattern);
573
+ }
574
+ }
575
+ if (trimmed.includes("exclude") || trimmed.includes("ignore")) {
576
+ const matches = trimmed.match(/['"`]([^'"`]+\.(log|tmp|cache|temp))['"`]/g);
577
+ if (matches) {
578
+ patterns.push(...matches.map((m) => m.replace(/['"`]/g, "")));
579
+ }
580
+ }
581
+ }
582
+ return patterns;
583
+ }
584
+
417
585
  // src/generators/rules/claudecode.ts
418
586
  var import_node_path4 = require("path");
419
587
 
420
588
  // src/types/claudecode.ts
421
- var import_v4_mini2 = require("zod/v4-mini");
422
- var ClaudeSettingsSchema = import_v4_mini2.z.looseObject({
423
- permissions: import_v4_mini2.z._default(
424
- import_v4_mini2.z.looseObject({
425
- deny: import_v4_mini2.z._default(import_v4_mini2.z.array(import_v4_mini2.z.string()), [])
589
+ var import_mini2 = require("zod/mini");
590
+ var ClaudeSettingsSchema = import_mini2.z.looseObject({
591
+ permissions: import_mini2.z._default(
592
+ import_mini2.z.looseObject({
593
+ deny: import_mini2.z._default(import_mini2.z.array(import_mini2.z.string()), [])
426
594
  }),
427
595
  { deny: [] }
428
596
  )
429
597
  });
430
598
 
431
599
  // src/utils/file.ts
432
- var import_promises3 = require("fs/promises");
433
- var import_node_path3 = require("path");
434
-
435
- // src/utils/file-ops.ts
436
600
  var import_promises2 = require("fs/promises");
437
- var import_node_path = require("path");
601
+ var import_node_path2 = require("path");
438
602
  async function ensureDir(dirPath) {
439
603
  try {
440
604
  await (0, import_promises2.stat)(dirPath);
@@ -446,7 +610,7 @@ async function readFileContent(filepath) {
446
610
  return (0, import_promises2.readFile)(filepath, "utf-8");
447
611
  }
448
612
  async function writeFileContent(filepath, content) {
449
- await ensureDir((0, import_node_path.dirname)(filepath));
613
+ await ensureDir((0, import_node_path2.dirname)(filepath));
450
614
  await (0, import_promises2.writeFile)(filepath, content, "utf-8");
451
615
  }
452
616
  async function fileExists(filepath) {
@@ -457,16 +621,57 @@ async function fileExists(filepath) {
457
621
  return false;
458
622
  }
459
623
  }
624
+ async function findFiles(dir, extension = ".md") {
625
+ try {
626
+ const files = await (0, import_promises2.readdir)(dir);
627
+ return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path2.join)(dir, file));
628
+ } catch {
629
+ return [];
630
+ }
631
+ }
632
+ async function removeDirectory(dirPath) {
633
+ const dangerousPaths = [".", "/", "~", "src", "node_modules"];
634
+ if (dangerousPaths.includes(dirPath) || dirPath === "") {
635
+ console.warn(`Skipping deletion of dangerous path: ${dirPath}`);
636
+ return;
637
+ }
638
+ try {
639
+ if (await fileExists(dirPath)) {
640
+ await (0, import_promises2.rm)(dirPath, { recursive: true, force: true });
641
+ }
642
+ } catch (error) {
643
+ console.warn(`Failed to remove directory ${dirPath}:`, error);
644
+ }
645
+ }
646
+ async function removeFile(filepath) {
647
+ try {
648
+ if (await fileExists(filepath)) {
649
+ await (0, import_promises2.rm)(filepath);
650
+ }
651
+ } catch (error) {
652
+ console.warn(`Failed to remove file ${filepath}:`, error);
653
+ }
654
+ }
655
+ async function removeClaudeGeneratedFiles() {
656
+ const filesToRemove = ["CLAUDE.md", ".claude/memories"];
657
+ for (const fileOrDir of filesToRemove) {
658
+ if (fileOrDir.endsWith("/memories")) {
659
+ await removeDirectory(fileOrDir);
660
+ } else {
661
+ await removeFile(fileOrDir);
662
+ }
663
+ }
664
+ }
460
665
 
461
666
  // src/utils/ignore.ts
462
- var import_node_path2 = require("path");
667
+ var import_node_path3 = require("path");
463
668
  var import_micromatch = __toESM(require("micromatch"), 1);
464
669
  var cachedIgnorePatterns = null;
465
670
  async function loadIgnorePatterns(baseDir = process.cwd()) {
466
671
  if (cachedIgnorePatterns) {
467
672
  return cachedIgnorePatterns;
468
673
  }
469
- const ignorePath = (0, import_node_path2.join)(baseDir, ".rulesyncignore");
674
+ const ignorePath = (0, import_node_path3.join)(baseDir, ".rulesyncignore");
470
675
  if (!await fileExists(ignorePath)) {
471
676
  cachedIgnorePatterns = { patterns: [] };
472
677
  return cachedIgnorePatterns;
@@ -509,53 +714,6 @@ function filterIgnoredFiles(files, ignorePatterns) {
509
714
  return files.filter((file) => !isFileIgnored(file, ignorePatterns));
510
715
  }
511
716
 
512
- // src/utils/file.ts
513
- async function findFiles(dir, extension = ".md", ignorePatterns) {
514
- try {
515
- const files = await (0, import_promises3.readdir)(dir);
516
- const filtered = files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path3.join)(dir, file));
517
- if (ignorePatterns && ignorePatterns.length > 0) {
518
- return filterIgnoredFiles(filtered, ignorePatterns);
519
- }
520
- return filtered;
521
- } catch {
522
- return [];
523
- }
524
- }
525
- async function removeDirectory(dirPath) {
526
- const dangerousPaths = [".", "/", "~", "src", "node_modules"];
527
- if (dangerousPaths.includes(dirPath) || dirPath === "") {
528
- console.warn(`Skipping deletion of dangerous path: ${dirPath}`);
529
- return;
530
- }
531
- try {
532
- if (await fileExists(dirPath)) {
533
- await (0, import_promises3.rm)(dirPath, { recursive: true, force: true });
534
- }
535
- } catch (error) {
536
- console.warn(`Failed to remove directory ${dirPath}:`, error);
537
- }
538
- }
539
- async function removeFile(filepath) {
540
- try {
541
- if (await fileExists(filepath)) {
542
- await (0, import_promises3.rm)(filepath);
543
- }
544
- } catch (error) {
545
- console.warn(`Failed to remove file ${filepath}:`, error);
546
- }
547
- }
548
- async function removeClaudeGeneratedFiles() {
549
- const filesToRemove = ["CLAUDE.md", ".claude/memories"];
550
- for (const fileOrDir of filesToRemove) {
551
- if (fileOrDir.endsWith("/memories")) {
552
- await removeDirectory(fileOrDir);
553
- } else {
554
- await removeFile(fileOrDir);
555
- }
556
- }
557
- }
558
-
559
717
  // src/generators/rules/claudecode.ts
560
718
  async function generateClaudecodeConfig(rules, config, baseDir) {
561
719
  const outputs = [];
@@ -892,14 +1050,34 @@ function generateAiexclude(patterns) {
892
1050
  return lines.join("\n");
893
1051
  }
894
1052
 
895
- // src/generators/rules/roo.ts
1053
+ // src/generators/rules/kiro.ts
896
1054
  var import_node_path9 = require("path");
1055
+ async function generateKiroConfig(rules, config, baseDir) {
1056
+ const outputs = [];
1057
+ for (const rule of rules) {
1058
+ const content = generateKiroMarkdown(rule);
1059
+ const outputDir = baseDir ? (0, import_node_path9.join)(baseDir, config.outputPaths.kiro) : config.outputPaths.kiro;
1060
+ const filepath = (0, import_node_path9.join)(outputDir, `${rule.filename}.md`);
1061
+ outputs.push({
1062
+ tool: "kiro",
1063
+ filepath,
1064
+ content
1065
+ });
1066
+ }
1067
+ return outputs;
1068
+ }
1069
+ function generateKiroMarkdown(rule) {
1070
+ return rule.content.trim();
1071
+ }
1072
+
1073
+ // src/generators/rules/roo.ts
1074
+ var import_node_path10 = require("path");
897
1075
  async function generateRooConfig(rules, config, baseDir) {
898
1076
  const outputs = [];
899
1077
  for (const rule of rules) {
900
1078
  const content = generateRooMarkdown(rule);
901
- const outputDir = baseDir ? (0, import_node_path9.join)(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
902
- const filepath = (0, import_node_path9.join)(outputDir, `${rule.filename}.md`);
1079
+ const outputDir = baseDir ? (0, import_node_path10.join)(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
1080
+ const filepath = (0, import_node_path10.join)(outputDir, `${rule.filename}.md`);
903
1081
  outputs.push({
904
1082
  tool: "roo",
905
1083
  filepath,
@@ -908,7 +1086,7 @@ async function generateRooConfig(rules, config, baseDir) {
908
1086
  }
909
1087
  const ignorePatterns = await loadIgnorePatterns(baseDir);
910
1088
  if (ignorePatterns.patterns.length > 0) {
911
- const rooIgnorePath = baseDir ? (0, import_node_path9.join)(baseDir, ".rooignore") : ".rooignore";
1089
+ const rooIgnorePath = baseDir ? (0, import_node_path10.join)(baseDir, ".rooignore") : ".rooignore";
912
1090
  const rooIgnoreContent = generateRooIgnore(ignorePatterns.patterns);
913
1091
  outputs.push({
914
1092
  tool: "roo",
@@ -974,6 +1152,11 @@ async function generateForTool(tool, rules, config, baseDir) {
974
1152
  return generateRooConfig(rules, config, baseDir);
975
1153
  case "geminicli":
976
1154
  return generateGeminiConfig(rules, config, baseDir);
1155
+ case "kiro": {
1156
+ const kiroRulesOutputs = await generateKiroConfig(rules, config, baseDir);
1157
+ const kiroIgnoreOutputs = await generateKiroIgnoreFiles(rules, config, baseDir);
1158
+ return [...kiroRulesOutputs, ...kiroIgnoreOutputs];
1159
+ }
977
1160
  default:
978
1161
  console.warn(`Unknown tool: ${tool}`);
979
1162
  return null;
@@ -981,74 +1164,76 @@ async function generateForTool(tool, rules, config, baseDir) {
981
1164
  }
982
1165
 
983
1166
  // src/core/parser.ts
984
- var import_node_path10 = require("path");
1167
+ var import_node_path11 = require("path");
985
1168
  var import_gray_matter = __toESM(require("gray-matter"), 1);
986
1169
 
987
1170
  // src/types/config.ts
988
- var import_v4_mini3 = require("zod/v4-mini");
1171
+ var import_mini3 = require("zod/mini");
989
1172
  init_tool_targets();
990
- var ConfigSchema = import_v4_mini3.z.object({
991
- aiRulesDir: import_v4_mini3.z.string(),
992
- outputPaths: import_v4_mini3.z.record(ToolTargetSchema, import_v4_mini3.z.string()),
993
- watchEnabled: import_v4_mini3.z.boolean(),
1173
+ var ConfigSchema = import_mini3.z.object({
1174
+ aiRulesDir: import_mini3.z.string(),
1175
+ outputPaths: import_mini3.z.record(ToolTargetSchema, import_mini3.z.string()),
1176
+ watchEnabled: import_mini3.z.boolean(),
994
1177
  defaultTargets: ToolTargetsSchema
995
1178
  });
996
1179
 
997
1180
  // src/types/mcp.ts
998
- var import_v4_mini4 = require("zod/v4-mini");
1181
+ var import_mini4 = require("zod/mini");
999
1182
  init_tool_targets();
1000
- var McpTransportTypeSchema = import_v4_mini4.z.enum(["stdio", "sse", "http"]);
1001
- var McpServerBaseSchema = import_v4_mini4.z.object({
1002
- command: import_v4_mini4.z.optional(import_v4_mini4.z.string()),
1003
- args: import_v4_mini4.z.optional(import_v4_mini4.z.array(import_v4_mini4.z.string())),
1004
- url: import_v4_mini4.z.optional(import_v4_mini4.z.string()),
1005
- httpUrl: import_v4_mini4.z.optional(import_v4_mini4.z.string()),
1006
- env: import_v4_mini4.z.optional(import_v4_mini4.z.record(import_v4_mini4.z.string(), import_v4_mini4.z.string())),
1007
- disabled: import_v4_mini4.z.optional(import_v4_mini4.z.boolean()),
1008
- networkTimeout: import_v4_mini4.z.optional(import_v4_mini4.z.number()),
1009
- timeout: import_v4_mini4.z.optional(import_v4_mini4.z.number()),
1010
- trust: import_v4_mini4.z.optional(import_v4_mini4.z.boolean()),
1011
- cwd: import_v4_mini4.z.optional(import_v4_mini4.z.string()),
1012
- transport: import_v4_mini4.z.optional(McpTransportTypeSchema),
1013
- type: import_v4_mini4.z.optional(import_v4_mini4.z.enum(["sse", "streamable-http"])),
1014
- alwaysAllow: import_v4_mini4.z.optional(import_v4_mini4.z.array(import_v4_mini4.z.string())),
1015
- tools: import_v4_mini4.z.optional(import_v4_mini4.z.array(import_v4_mini4.z.string()))
1183
+ var McpTransportTypeSchema = import_mini4.z.enum(["stdio", "sse", "http"]);
1184
+ var McpServerBaseSchema = import_mini4.z.object({
1185
+ command: import_mini4.z.optional(import_mini4.z.string()),
1186
+ args: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
1187
+ url: import_mini4.z.optional(import_mini4.z.string()),
1188
+ httpUrl: import_mini4.z.optional(import_mini4.z.string()),
1189
+ env: import_mini4.z.optional(import_mini4.z.record(import_mini4.z.string(), import_mini4.z.string())),
1190
+ disabled: import_mini4.z.optional(import_mini4.z.boolean()),
1191
+ networkTimeout: import_mini4.z.optional(import_mini4.z.number()),
1192
+ timeout: import_mini4.z.optional(import_mini4.z.number()),
1193
+ trust: import_mini4.z.optional(import_mini4.z.boolean()),
1194
+ cwd: import_mini4.z.optional(import_mini4.z.string()),
1195
+ transport: import_mini4.z.optional(McpTransportTypeSchema),
1196
+ type: import_mini4.z.optional(import_mini4.z.enum(["sse", "streamable-http"])),
1197
+ alwaysAllow: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
1198
+ tools: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
1199
+ kiroAutoApprove: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string())),
1200
+ kiroAutoBlock: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string()))
1016
1201
  });
1017
- var RulesyncMcpServerSchema = import_v4_mini4.z.extend(McpServerBaseSchema, {
1018
- targets: import_v4_mini4.z.optional(RulesyncTargetsSchema)
1202
+ var RulesyncMcpServerSchema = import_mini4.z.extend(McpServerBaseSchema, {
1203
+ targets: import_mini4.z.optional(RulesyncTargetsSchema)
1019
1204
  });
1020
- var McpConfigSchema = import_v4_mini4.z.object({
1021
- mcpServers: import_v4_mini4.z.record(import_v4_mini4.z.string(), McpServerBaseSchema)
1205
+ var McpConfigSchema = import_mini4.z.object({
1206
+ mcpServers: import_mini4.z.record(import_mini4.z.string(), McpServerBaseSchema)
1022
1207
  });
1023
- var RulesyncMcpConfigSchema = import_v4_mini4.z.object({
1024
- mcpServers: import_v4_mini4.z.record(import_v4_mini4.z.string(), RulesyncMcpServerSchema)
1208
+ var RulesyncMcpConfigSchema = import_mini4.z.object({
1209
+ mcpServers: import_mini4.z.record(import_mini4.z.string(), RulesyncMcpServerSchema)
1025
1210
  });
1026
1211
 
1027
1212
  // src/types/rules.ts
1028
- var import_v4_mini5 = require("zod/v4-mini");
1213
+ var import_mini5 = require("zod/mini");
1029
1214
  init_tool_targets();
1030
- var RuleFrontmatterSchema = import_v4_mini5.z.object({
1031
- root: import_v4_mini5.z.boolean(),
1215
+ var RuleFrontmatterSchema = import_mini5.z.object({
1216
+ root: import_mini5.z.boolean(),
1032
1217
  targets: RulesyncTargetsSchema,
1033
- description: import_v4_mini5.z.string(),
1034
- globs: import_v4_mini5.z.array(import_v4_mini5.z.string()),
1035
- cursorRuleType: import_v4_mini5.z.optional(import_v4_mini5.z.enum(["always", "manual", "specificFiles", "intelligently"]))
1218
+ description: import_mini5.z.string(),
1219
+ globs: import_mini5.z.array(import_mini5.z.string()),
1220
+ cursorRuleType: import_mini5.z.optional(import_mini5.z.enum(["always", "manual", "specificFiles", "intelligently"]))
1036
1221
  });
1037
- var ParsedRuleSchema = import_v4_mini5.z.object({
1222
+ var ParsedRuleSchema = import_mini5.z.object({
1038
1223
  frontmatter: RuleFrontmatterSchema,
1039
- content: import_v4_mini5.z.string(),
1040
- filename: import_v4_mini5.z.string(),
1041
- filepath: import_v4_mini5.z.string()
1224
+ content: import_mini5.z.string(),
1225
+ filename: import_mini5.z.string(),
1226
+ filepath: import_mini5.z.string()
1042
1227
  });
1043
- var GeneratedOutputSchema = import_v4_mini5.z.object({
1228
+ var GeneratedOutputSchema = import_mini5.z.object({
1044
1229
  tool: ToolTargetSchema,
1045
- filepath: import_v4_mini5.z.string(),
1046
- content: import_v4_mini5.z.string()
1230
+ filepath: import_mini5.z.string(),
1231
+ content: import_mini5.z.string()
1047
1232
  });
1048
- var GenerateOptionsSchema = import_v4_mini5.z.object({
1049
- targetTools: import_v4_mini5.z.optional(ToolTargetsSchema),
1050
- outputDir: import_v4_mini5.z.optional(import_v4_mini5.z.string()),
1051
- watch: import_v4_mini5.z.optional(import_v4_mini5.z.boolean())
1233
+ var GenerateOptionsSchema = import_mini5.z.object({
1234
+ targetTools: import_mini5.z.optional(ToolTargetsSchema),
1235
+ outputDir: import_mini5.z.optional(import_mini5.z.string()),
1236
+ watch: import_mini5.z.optional(import_mini5.z.boolean())
1052
1237
  });
1053
1238
 
1054
1239
  // src/types/index.ts
@@ -1057,7 +1242,8 @@ init_tool_targets();
1057
1242
  // src/core/parser.ts
1058
1243
  async function parseRulesFromDirectory(aiRulesDir) {
1059
1244
  const ignorePatterns = await loadIgnorePatterns();
1060
- const ruleFiles = await findFiles(aiRulesDir, ".md", ignorePatterns.patterns);
1245
+ const allRuleFiles = await findFiles(aiRulesDir, ".md");
1246
+ const ruleFiles = filterIgnoredFiles(allRuleFiles, ignorePatterns.patterns);
1061
1247
  const rules = [];
1062
1248
  const errors = [];
1063
1249
  if (ignorePatterns.patterns.length > 0) {
@@ -1090,7 +1276,7 @@ async function parseRuleFile(filepath) {
1090
1276
  const parsed = (0, import_gray_matter.default)(content);
1091
1277
  try {
1092
1278
  const frontmatter = RuleFrontmatterSchema.parse(parsed.data);
1093
- const filename = (0, import_node_path10.basename)(filepath, ".md");
1279
+ const filename = (0, import_node_path11.basename)(filepath, ".md");
1094
1280
  return {
1095
1281
  frontmatter,
1096
1282
  content: parsed.content,
@@ -1163,6 +1349,7 @@ init_cline();
1163
1349
  init_copilot();
1164
1350
  init_cursor();
1165
1351
  init_geminicli();
1352
+ init_kiro();
1166
1353
  init_roo();
1167
1354
 
1168
1355
  // src/core/mcp-parser.ts
@@ -1226,6 +1413,11 @@ async function generateMcpConfigs(projectRoot, baseDir) {
1226
1413
  path: path3.join(targetRoot, ".gemini", "settings.json"),
1227
1414
  generate: () => generateGeminiCliMcp(config)
1228
1415
  },
1416
+ {
1417
+ tool: "kiro-project",
1418
+ path: path3.join(targetRoot, ".kiro", "mcp.json"),
1419
+ generate: () => generateKiroMcp(config)
1420
+ },
1229
1421
  {
1230
1422
  tool: "roo-project",
1231
1423
  path: path3.join(targetRoot, ".roo", "mcp.json"),
@@ -1236,7 +1428,7 @@ async function generateMcpConfigs(projectRoot, baseDir) {
1236
1428
  try {
1237
1429
  const content = generator.generate();
1238
1430
  const parsed = JSON.parse(content);
1239
- if (generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("roo")) {
1431
+ if (generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("kiro") || generator.tool.includes("roo")) {
1240
1432
  if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
1241
1433
  results.push({
1242
1434
  tool: generator.tool,
@@ -1322,6 +1514,9 @@ async function generateCommand(options = {}) {
1322
1514
  case "geminicli":
1323
1515
  deleteTasks.push(removeDirectory(config.outputPaths.geminicli));
1324
1516
  break;
1517
+ case "kiro":
1518
+ deleteTasks.push(removeDirectory(config.outputPaths.kiro));
1519
+ break;
1325
1520
  }
1326
1521
  }
1327
1522
  await Promise.all(deleteTasks);
@@ -1352,11 +1547,10 @@ Generating configurations for base directory: ${baseDir}`);
1352
1547
  console.warn("\u26A0\uFE0F No configurations generated");
1353
1548
  return;
1354
1549
  }
1355
- console.log(`
1356
- \u{1F389} Successfully generated ${totalOutputs} configuration file(s)!`);
1357
1550
  if (options.verbose) {
1358
1551
  console.log("\nGenerating MCP configurations...");
1359
1552
  }
1553
+ let totalMcpOutputs = 0;
1360
1554
  for (const baseDir of baseDirs) {
1361
1555
  const mcpResults = await generateMcpConfigs(
1362
1556
  process.cwd(),
@@ -1371,6 +1565,7 @@ Generating configurations for base directory: ${baseDir}`);
1371
1565
  for (const result of mcpResults) {
1372
1566
  if (result.status === "success") {
1373
1567
  console.log(`\u2705 Generated ${result.tool} MCP configuration: ${result.path}`);
1568
+ totalMcpOutputs++;
1374
1569
  } else if (result.status === "error") {
1375
1570
  console.error(`\u274C Failed to generate ${result.tool} MCP configuration: ${result.error}`);
1376
1571
  } else if (options.verbose && result.status === "skipped") {
@@ -1378,6 +1573,13 @@ Generating configurations for base directory: ${baseDir}`);
1378
1573
  }
1379
1574
  }
1380
1575
  }
1576
+ const totalGenerated = totalOutputs + totalMcpOutputs;
1577
+ if (totalGenerated > 0) {
1578
+ console.log(
1579
+ `
1580
+ \u{1F389} All done! Generated ${totalGenerated} file(s) total (${totalOutputs} configurations + ${totalMcpOutputs} MCP configurations)`
1581
+ );
1582
+ }
1381
1583
  } catch (error) {
1382
1584
  console.error("\u274C Failed to generate configurations:", error);
1383
1585
  process.exit(1);
@@ -1386,9 +1588,9 @@ Generating configurations for base directory: ${baseDir}`);
1386
1588
 
1387
1589
  // src/cli/commands/gitignore.ts
1388
1590
  var import_node_fs = require("fs");
1389
- var import_node_path11 = require("path");
1591
+ var import_node_path12 = require("path");
1390
1592
  var gitignoreCommand = async () => {
1391
- const gitignorePath = (0, import_node_path11.join)(process.cwd(), ".gitignore");
1593
+ const gitignorePath = (0, import_node_path12.join)(process.cwd(), ".gitignore");
1392
1594
  const rulesFilesToIgnore = [
1393
1595
  "# Generated by rulesync - AI tool configuration files",
1394
1596
  "**/.github/copilot-instructions.md",
@@ -1405,6 +1607,8 @@ var gitignoreCommand = async () => {
1405
1607
  "**/GEMINI.md",
1406
1608
  "**/.gemini/memories/",
1407
1609
  "**/.aiexclude",
1610
+ "**/.aiignore",
1611
+ "**/.kiro/steering/",
1408
1612
  "**/.mcp.json",
1409
1613
  "!.rulesync/.mcp.json",
1410
1614
  "**/.cursor/mcp.json",
@@ -1442,17 +1646,17 @@ ${linesToAdd.join("\n")}
1442
1646
  };
1443
1647
 
1444
1648
  // src/core/importer.ts
1445
- var import_node_path18 = require("path");
1649
+ var import_node_path19 = require("path");
1446
1650
  var import_gray_matter4 = __toESM(require("gray-matter"), 1);
1447
1651
 
1448
1652
  // src/parsers/claudecode.ts
1449
- var import_node_path12 = require("path");
1653
+ var import_node_path13 = require("path");
1450
1654
  async function parseClaudeConfiguration(baseDir = process.cwd()) {
1451
1655
  const errors = [];
1452
1656
  const rules = [];
1453
1657
  let ignorePatterns;
1454
1658
  let mcpServers;
1455
- const claudeFilePath = (0, import_node_path12.join)(baseDir, "CLAUDE.md");
1659
+ const claudeFilePath = (0, import_node_path13.join)(baseDir, "CLAUDE.md");
1456
1660
  if (!await fileExists(claudeFilePath)) {
1457
1661
  errors.push("CLAUDE.md file not found");
1458
1662
  return { rules, errors };
@@ -1463,12 +1667,12 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
1463
1667
  if (mainRule) {
1464
1668
  rules.push(mainRule);
1465
1669
  }
1466
- const memoryDir = (0, import_node_path12.join)(baseDir, ".claude", "memories");
1670
+ const memoryDir = (0, import_node_path13.join)(baseDir, ".claude", "memories");
1467
1671
  if (await fileExists(memoryDir)) {
1468
1672
  const memoryRules = await parseClaudeMemoryFiles(memoryDir);
1469
1673
  rules.push(...memoryRules);
1470
1674
  }
1471
- const settingsPath = (0, import_node_path12.join)(baseDir, ".claude", "settings.json");
1675
+ const settingsPath = (0, import_node_path13.join)(baseDir, ".claude", "settings.json");
1472
1676
  if (await fileExists(settingsPath)) {
1473
1677
  const settingsResult = await parseClaudeSettings(settingsPath);
1474
1678
  if (settingsResult.ignorePatterns) {
@@ -1525,10 +1729,10 @@ async function parseClaudeMemoryFiles(memoryDir) {
1525
1729
  const files = await readdir2(memoryDir);
1526
1730
  for (const file of files) {
1527
1731
  if (file.endsWith(".md")) {
1528
- const filePath = (0, import_node_path12.join)(memoryDir, file);
1732
+ const filePath = (0, import_node_path13.join)(memoryDir, file);
1529
1733
  const content = await readFileContent(filePath);
1530
1734
  if (content.trim()) {
1531
- const filename = (0, import_node_path12.basename)(file, ".md");
1735
+ const filename = (0, import_node_path13.basename)(file, ".md");
1532
1736
  const frontmatter = {
1533
1737
  root: false,
1534
1738
  targets: ["claudecode"],
@@ -1588,11 +1792,11 @@ async function parseClaudeSettings(settingsPath) {
1588
1792
  }
1589
1793
 
1590
1794
  // src/parsers/cline.ts
1591
- var import_node_path13 = require("path");
1795
+ var import_node_path14 = require("path");
1592
1796
  async function parseClineConfiguration(baseDir = process.cwd()) {
1593
1797
  const errors = [];
1594
1798
  const rules = [];
1595
- const clineFilePath = (0, import_node_path13.join)(baseDir, ".cline", "instructions.md");
1799
+ const clineFilePath = (0, import_node_path14.join)(baseDir, ".cline", "instructions.md");
1596
1800
  if (await fileExists(clineFilePath)) {
1597
1801
  try {
1598
1802
  const content = await readFileContent(clineFilePath);
@@ -1615,14 +1819,14 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
1615
1819
  errors.push(`Failed to parse .cline/instructions.md: ${errorMessage}`);
1616
1820
  }
1617
1821
  }
1618
- const clinerulesDirPath = (0, import_node_path13.join)(baseDir, ".clinerules");
1822
+ const clinerulesDirPath = (0, import_node_path14.join)(baseDir, ".clinerules");
1619
1823
  if (await fileExists(clinerulesDirPath)) {
1620
1824
  try {
1621
1825
  const { readdir: readdir2 } = await import("fs/promises");
1622
1826
  const files = await readdir2(clinerulesDirPath);
1623
1827
  for (const file of files) {
1624
1828
  if (file.endsWith(".md")) {
1625
- const filePath = (0, import_node_path13.join)(clinerulesDirPath, file);
1829
+ const filePath = (0, import_node_path14.join)(clinerulesDirPath, file);
1626
1830
  try {
1627
1831
  const content = await readFileContent(filePath);
1628
1832
  if (content.trim()) {
@@ -1658,12 +1862,12 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
1658
1862
  }
1659
1863
 
1660
1864
  // src/parsers/copilot.ts
1661
- var import_node_path14 = require("path");
1865
+ var import_node_path15 = require("path");
1662
1866
  var import_gray_matter2 = __toESM(require("gray-matter"), 1);
1663
1867
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
1664
1868
  const errors = [];
1665
1869
  const rules = [];
1666
- const copilotFilePath = (0, import_node_path14.join)(baseDir, ".github", "copilot-instructions.md");
1870
+ const copilotFilePath = (0, import_node_path15.join)(baseDir, ".github", "copilot-instructions.md");
1667
1871
  if (await fileExists(copilotFilePath)) {
1668
1872
  try {
1669
1873
  const rawContent = await readFileContent(copilotFilePath);
@@ -1688,19 +1892,19 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
1688
1892
  errors.push(`Failed to parse copilot-instructions.md: ${errorMessage}`);
1689
1893
  }
1690
1894
  }
1691
- const instructionsDir = (0, import_node_path14.join)(baseDir, ".github", "instructions");
1895
+ const instructionsDir = (0, import_node_path15.join)(baseDir, ".github", "instructions");
1692
1896
  if (await fileExists(instructionsDir)) {
1693
1897
  try {
1694
1898
  const { readdir: readdir2 } = await import("fs/promises");
1695
1899
  const files = await readdir2(instructionsDir);
1696
1900
  for (const file of files) {
1697
1901
  if (file.endsWith(".instructions.md")) {
1698
- const filePath = (0, import_node_path14.join)(instructionsDir, file);
1902
+ const filePath = (0, import_node_path15.join)(instructionsDir, file);
1699
1903
  const rawContent = await readFileContent(filePath);
1700
1904
  const parsed = (0, import_gray_matter2.default)(rawContent);
1701
1905
  const content = parsed.content.trim();
1702
1906
  if (content) {
1703
- const filename = (0, import_node_path14.basename)(file, ".instructions.md");
1907
+ const filename = (0, import_node_path15.basename)(file, ".instructions.md");
1704
1908
  const frontmatter = {
1705
1909
  root: false,
1706
1910
  targets: ["copilot"],
@@ -1730,10 +1934,10 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
1730
1934
  }
1731
1935
 
1732
1936
  // src/parsers/cursor.ts
1733
- var import_node_path15 = require("path");
1937
+ var import_node_path16 = require("path");
1734
1938
  var import_gray_matter3 = __toESM(require("gray-matter"), 1);
1735
1939
  var import_js_yaml = require("js-yaml");
1736
- var import_v4_mini6 = require("zod/v4-mini");
1940
+ var import_mini6 = require("zod/mini");
1737
1941
  var customMatterOptions = {
1738
1942
  engines: {
1739
1943
  yaml: {
@@ -1761,7 +1965,7 @@ var customMatterOptions = {
1761
1965
  }
1762
1966
  };
1763
1967
  function convertCursorMdcFrontmatter(cursorFrontmatter, _filename) {
1764
- const FrontmatterSchema = import_v4_mini6.z.record(import_v4_mini6.z.string(), import_v4_mini6.z.unknown());
1968
+ const FrontmatterSchema = import_mini6.z.record(import_mini6.z.string(), import_mini6.z.unknown());
1765
1969
  const parseResult = FrontmatterSchema.safeParse(cursorFrontmatter);
1766
1970
  if (!parseResult.success) {
1767
1971
  return {
@@ -1855,7 +2059,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1855
2059
  const rules = [];
1856
2060
  let ignorePatterns;
1857
2061
  let mcpServers;
1858
- const cursorFilePath = (0, import_node_path15.join)(baseDir, ".cursorrules");
2062
+ const cursorFilePath = (0, import_node_path16.join)(baseDir, ".cursorrules");
1859
2063
  if (await fileExists(cursorFilePath)) {
1860
2064
  try {
1861
2065
  const rawContent = await readFileContent(cursorFilePath);
@@ -1876,20 +2080,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1876
2080
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
1877
2081
  }
1878
2082
  }
1879
- const cursorRulesDir = (0, import_node_path15.join)(baseDir, ".cursor", "rules");
2083
+ const cursorRulesDir = (0, import_node_path16.join)(baseDir, ".cursor", "rules");
1880
2084
  if (await fileExists(cursorRulesDir)) {
1881
2085
  try {
1882
2086
  const { readdir: readdir2 } = await import("fs/promises");
1883
2087
  const files = await readdir2(cursorRulesDir);
1884
2088
  for (const file of files) {
1885
2089
  if (file.endsWith(".mdc")) {
1886
- const filePath = (0, import_node_path15.join)(cursorRulesDir, file);
2090
+ const filePath = (0, import_node_path16.join)(cursorRulesDir, file);
1887
2091
  try {
1888
2092
  const rawContent = await readFileContent(filePath);
1889
2093
  const parsed = (0, import_gray_matter3.default)(rawContent, customMatterOptions);
1890
2094
  const content = parsed.content.trim();
1891
2095
  if (content) {
1892
- const filename = (0, import_node_path15.basename)(file, ".mdc");
2096
+ const filename = (0, import_node_path16.basename)(file, ".mdc");
1893
2097
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
1894
2098
  rules.push({
1895
2099
  frontmatter,
@@ -1912,7 +2116,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1912
2116
  if (rules.length === 0) {
1913
2117
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
1914
2118
  }
1915
- const cursorIgnorePath = (0, import_node_path15.join)(baseDir, ".cursorignore");
2119
+ const cursorIgnorePath = (0, import_node_path16.join)(baseDir, ".cursorignore");
1916
2120
  if (await fileExists(cursorIgnorePath)) {
1917
2121
  try {
1918
2122
  const content = await readFileContent(cursorIgnorePath);
@@ -1925,7 +2129,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1925
2129
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
1926
2130
  }
1927
2131
  }
1928
- const cursorMcpPath = (0, import_node_path15.join)(baseDir, ".cursor", "mcp.json");
2132
+ const cursorMcpPath = (0, import_node_path16.join)(baseDir, ".cursor", "mcp.json");
1929
2133
  if (await fileExists(cursorMcpPath)) {
1930
2134
  try {
1931
2135
  const content = await readFileContent(cursorMcpPath);
@@ -1948,13 +2152,13 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
1948
2152
  }
1949
2153
 
1950
2154
  // src/parsers/geminicli.ts
1951
- var import_node_path16 = require("path");
2155
+ var import_node_path17 = require("path");
1952
2156
  async function parseGeminiConfiguration(baseDir = process.cwd()) {
1953
2157
  const errors = [];
1954
2158
  const rules = [];
1955
2159
  let ignorePatterns;
1956
2160
  let mcpServers;
1957
- const geminiFilePath = (0, import_node_path16.join)(baseDir, "GEMINI.md");
2161
+ const geminiFilePath = (0, import_node_path17.join)(baseDir, "GEMINI.md");
1958
2162
  if (!await fileExists(geminiFilePath)) {
1959
2163
  errors.push("GEMINI.md file not found");
1960
2164
  return { rules, errors };
@@ -1965,12 +2169,12 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
1965
2169
  if (mainRule) {
1966
2170
  rules.push(mainRule);
1967
2171
  }
1968
- const memoryDir = (0, import_node_path16.join)(baseDir, ".gemini", "memories");
2172
+ const memoryDir = (0, import_node_path17.join)(baseDir, ".gemini", "memories");
1969
2173
  if (await fileExists(memoryDir)) {
1970
2174
  const memoryRules = await parseGeminiMemoryFiles(memoryDir);
1971
2175
  rules.push(...memoryRules);
1972
2176
  }
1973
- const settingsPath = (0, import_node_path16.join)(baseDir, ".gemini", "settings.json");
2177
+ const settingsPath = (0, import_node_path17.join)(baseDir, ".gemini", "settings.json");
1974
2178
  if (await fileExists(settingsPath)) {
1975
2179
  const settingsResult = await parseGeminiSettings(settingsPath);
1976
2180
  if (settingsResult.ignorePatterns) {
@@ -1981,7 +2185,7 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
1981
2185
  }
1982
2186
  errors.push(...settingsResult.errors);
1983
2187
  }
1984
- const aiexcludePath = (0, import_node_path16.join)(baseDir, ".aiexclude");
2188
+ const aiexcludePath = (0, import_node_path17.join)(baseDir, ".aiexclude");
1985
2189
  if (await fileExists(aiexcludePath)) {
1986
2190
  const aiexcludePatterns = await parseAiexclude(aiexcludePath);
1987
2191
  if (aiexcludePatterns.length > 0) {
@@ -2034,10 +2238,10 @@ async function parseGeminiMemoryFiles(memoryDir) {
2034
2238
  const files = await readdir2(memoryDir);
2035
2239
  for (const file of files) {
2036
2240
  if (file.endsWith(".md")) {
2037
- const filePath = (0, import_node_path16.join)(memoryDir, file);
2241
+ const filePath = (0, import_node_path17.join)(memoryDir, file);
2038
2242
  const content = await readFileContent(filePath);
2039
2243
  if (content.trim()) {
2040
- const filename = (0, import_node_path16.basename)(file, ".md");
2244
+ const filename = (0, import_node_path17.basename)(file, ".md");
2041
2245
  const frontmatter = {
2042
2246
  root: false,
2043
2247
  targets: ["geminicli"],
@@ -2087,11 +2291,11 @@ async function parseAiexclude(aiexcludePath) {
2087
2291
  }
2088
2292
 
2089
2293
  // src/parsers/roo.ts
2090
- var import_node_path17 = require("path");
2294
+ var import_node_path18 = require("path");
2091
2295
  async function parseRooConfiguration(baseDir = process.cwd()) {
2092
2296
  const errors = [];
2093
2297
  const rules = [];
2094
- const rooFilePath = (0, import_node_path17.join)(baseDir, ".roo", "instructions.md");
2298
+ const rooFilePath = (0, import_node_path18.join)(baseDir, ".roo", "instructions.md");
2095
2299
  if (await fileExists(rooFilePath)) {
2096
2300
  try {
2097
2301
  const content = await readFileContent(rooFilePath);
@@ -2114,14 +2318,14 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
2114
2318
  errors.push(`Failed to parse .roo/instructions.md: ${errorMessage}`);
2115
2319
  }
2116
2320
  }
2117
- const rooRulesDir = (0, import_node_path17.join)(baseDir, ".roo", "rules");
2321
+ const rooRulesDir = (0, import_node_path18.join)(baseDir, ".roo", "rules");
2118
2322
  if (await fileExists(rooRulesDir)) {
2119
2323
  try {
2120
2324
  const { readdir: readdir2 } = await import("fs/promises");
2121
2325
  const files = await readdir2(rooRulesDir);
2122
2326
  for (const file of files) {
2123
2327
  if (file.endsWith(".md")) {
2124
- const filePath = (0, import_node_path17.join)(rooRulesDir, file);
2328
+ const filePath = (0, import_node_path18.join)(rooRulesDir, file);
2125
2329
  try {
2126
2330
  const content = await readFileContent(filePath);
2127
2331
  if (content.trim()) {
@@ -2222,7 +2426,7 @@ async function importConfiguration(options) {
2222
2426
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
2223
2427
  return { success: false, rulesCreated: 0, errors };
2224
2428
  }
2225
- const rulesDirPath = (0, import_node_path18.join)(baseDir, rulesDir);
2429
+ const rulesDirPath = (0, import_node_path19.join)(baseDir, rulesDir);
2226
2430
  try {
2227
2431
  const { mkdir: mkdir3 } = await import("fs/promises");
2228
2432
  await mkdir3(rulesDirPath, { recursive: true });
@@ -2236,7 +2440,7 @@ async function importConfiguration(options) {
2236
2440
  try {
2237
2441
  const baseFilename = `${tool}__${rule.filename}`;
2238
2442
  const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
2239
- const filePath = (0, import_node_path18.join)(rulesDirPath, `${filename}.md`);
2443
+ const filePath = (0, import_node_path19.join)(rulesDirPath, `${filename}.md`);
2240
2444
  const content = generateRuleFileContent(rule);
2241
2445
  await writeFileContent(filePath, content);
2242
2446
  rulesCreated++;
@@ -2251,7 +2455,7 @@ async function importConfiguration(options) {
2251
2455
  let ignoreFileCreated = false;
2252
2456
  if (ignorePatterns && ignorePatterns.length > 0) {
2253
2457
  try {
2254
- const rulesyncignorePath = (0, import_node_path18.join)(baseDir, ".rulesyncignore");
2458
+ const rulesyncignorePath = (0, import_node_path19.join)(baseDir, ".rulesyncignore");
2255
2459
  const ignoreContent = `${ignorePatterns.join("\n")}
2256
2460
  `;
2257
2461
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -2267,7 +2471,7 @@ async function importConfiguration(options) {
2267
2471
  let mcpFileCreated = false;
2268
2472
  if (mcpServers && Object.keys(mcpServers).length > 0) {
2269
2473
  try {
2270
- const mcpPath = (0, import_node_path18.join)(baseDir, rulesDir, ".mcp.json");
2474
+ const mcpPath = (0, import_node_path19.join)(baseDir, rulesDir, ".mcp.json");
2271
2475
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
2272
2476
  `;
2273
2477
  await writeFileContent(mcpPath, mcpContent);
@@ -2281,7 +2485,7 @@ async function importConfiguration(options) {
2281
2485
  }
2282
2486
  }
2283
2487
  return {
2284
- success: rulesCreated > 0 || ignoreFileCreated || mcpFileCreated,
2488
+ success: errors.length === 0 && (rulesCreated > 0 || ignoreFileCreated || mcpFileCreated),
2285
2489
  rulesCreated,
2286
2490
  errors,
2287
2491
  ignoreFileCreated,
@@ -2295,7 +2499,7 @@ function generateRuleFileContent(rule) {
2295
2499
  async function generateUniqueFilename(rulesDir, baseFilename) {
2296
2500
  let filename = baseFilename;
2297
2501
  let counter = 1;
2298
- while (await fileExists((0, import_node_path18.join)(rulesDir, `${filename}.md`))) {
2502
+ while (await fileExists((0, import_node_path19.join)(rulesDir, `${filename}.md`))) {
2299
2503
  filename = `${baseFilename}-${counter}`;
2300
2504
  counter++;
2301
2505
  }
@@ -2360,7 +2564,7 @@ async function importCommand(options = {}) {
2360
2564
  }
2361
2565
 
2362
2566
  // src/cli/commands/init.ts
2363
- var import_node_path19 = require("path");
2567
+ var import_node_path20 = require("path");
2364
2568
  async function initCommand() {
2365
2569
  const aiRulesDir = ".rulesync";
2366
2570
  console.log("Initializing rulesync...");
@@ -2407,7 +2611,7 @@ globs: ["**/*"]
2407
2611
  - Follow single responsibility principle
2408
2612
  `
2409
2613
  };
2410
- const filepath = (0, import_node_path19.join)(aiRulesDir, sampleFile.filename);
2614
+ const filepath = (0, import_node_path20.join)(aiRulesDir, sampleFile.filename);
2411
2615
  if (!await fileExists(filepath)) {
2412
2616
  await writeFileContent(filepath, sampleFile.content);
2413
2617
  console.log(`Created ${filepath}`);
@@ -2551,12 +2755,12 @@ async function watchCommand() {
2551
2755
 
2552
2756
  // src/cli/index.ts
2553
2757
  var program = new import_commander.Command();
2554
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.45.0");
2758
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.48.0");
2555
2759
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
2556
2760
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
2557
2761
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
2558
2762
  program.command("import").description("Import configurations from AI tools to rulesync format").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("-v, --verbose", "Verbose output").action(importCommand);
2559
- program.command("generate").description("Generate configuration files for AI tools").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("--delete", "Delete all existing files in output directories before generating").option(
2763
+ program.command("generate").description("Generate configuration files for AI tools").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("--kiro", "Generate only for Kiro IDE").option("--delete", "Delete all existing files in output directories before generating").option(
2560
2764
  "-b, --base-dir <paths>",
2561
2765
  "Base directories to generate files (comma-separated for multiple paths)"
2562
2766
  ).option("-v, --verbose", "Verbose output").action(async (options) => {
@@ -2567,6 +2771,7 @@ program.command("generate").description("Generate configuration files for AI too
2567
2771
  if (options.claudecode) tools.push("claudecode");
2568
2772
  if (options.roo) tools.push("roo");
2569
2773
  if (options.geminicli) tools.push("geminicli");
2774
+ if (options.kiro) tools.push("kiro");
2570
2775
  const generateOptions = {
2571
2776
  verbose: options.verbose,
2572
2777
  delete: options.delete