rulesync 0.57.0 → 0.59.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
@@ -9,6 +9,10 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
9
  var __esm = (fn, res) => function __init() {
10
10
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
11
  };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
12
16
  var __copyProps = (to, from, except, desc) => {
13
17
  if (from && typeof from === "object" || typeof from === "function") {
14
18
  for (let key of __getOwnPropNames(from))
@@ -82,6 +86,11 @@ var init_mcp_helpers = __esm({
82
86
  });
83
87
 
84
88
  // src/generators/mcp/augmentcode.ts
89
+ var augmentcode_exports = {};
90
+ __export(augmentcode_exports, {
91
+ generateAugmentcodeMcp: () => generateAugmentcodeMcp,
92
+ generateAugmentcodeMcpConfiguration: () => generateAugmentcodeMcpConfiguration
93
+ });
85
94
  function generateAugmentcodeMcp(config) {
86
95
  const augmentSettings = {
87
96
  mcpServers: []
@@ -131,6 +140,58 @@ function generateAugmentcodeMcp(config) {
131
140
  }
132
141
  return JSON.stringify(augmentSettings, null, 2);
133
142
  }
143
+ function generateAugmentcodeMcpConfiguration(mcpServers, baseDir = "") {
144
+ const filepath = baseDir ? `${baseDir}/.mcp.json` : ".mcp.json";
145
+ const settings = {
146
+ mcpServers: {}
147
+ };
148
+ for (const [serverName, server] of Object.entries(mcpServers)) {
149
+ if (!shouldIncludeServer(server, "augmentcode")) {
150
+ continue;
151
+ }
152
+ const { targets: _, ...serverConfig } = server;
153
+ const augmentServer = {};
154
+ if (serverConfig.command) {
155
+ augmentServer.command = serverConfig.command;
156
+ if (serverConfig.args) {
157
+ augmentServer.args = serverConfig.args;
158
+ }
159
+ if (serverConfig.env) {
160
+ augmentServer.env = serverConfig.env;
161
+ }
162
+ } else if (serverConfig.url || serverConfig.httpUrl) {
163
+ const url = serverConfig.httpUrl || serverConfig.url;
164
+ if (url) {
165
+ augmentServer.url = url;
166
+ }
167
+ if (serverConfig.httpUrl || serverConfig.transport === "http") {
168
+ augmentServer.transport = "http";
169
+ } else if (serverConfig.transport === "sse") {
170
+ augmentServer.transport = "sse";
171
+ }
172
+ if (serverConfig.env) {
173
+ augmentServer.headers = serverConfig.env;
174
+ }
175
+ }
176
+ if (serverConfig.timeout) {
177
+ augmentServer.timeout = serverConfig.timeout;
178
+ }
179
+ if (serverConfig.disabled !== void 0) {
180
+ augmentServer.enabled = !serverConfig.disabled;
181
+ }
182
+ if (serverConfig.networkTimeout && serverConfig.networkTimeout > 0) {
183
+ augmentServer.retries = Math.max(1, Math.floor(serverConfig.networkTimeout / 3e4));
184
+ }
185
+ settings.mcpServers[serverName] = augmentServer;
186
+ }
187
+ return [
188
+ {
189
+ filepath,
190
+ content: `${JSON.stringify(settings, null, 2)}
191
+ `
192
+ }
193
+ ];
194
+ }
134
195
  var init_augmentcode = __esm({
135
196
  "src/generators/mcp/augmentcode.ts"() {
136
197
  "use strict";
@@ -148,6 +209,20 @@ function generateMcpConfig(config, toolConfig) {
148
209
  const finalConfig = toolConfig.configWrapper(servers);
149
210
  return JSON.stringify(finalConfig, null, 2);
150
211
  }
212
+ function generateMcpConfigurationFiles(mcpServers, toolConfig, baseDir = "") {
213
+ const configs = [];
214
+ const rulesyncConfig = { mcpServers };
215
+ for (const configPath of toolConfig.configPaths) {
216
+ const filepath = baseDir ? `${baseDir}/${configPath}` : configPath;
217
+ const content = generateMcpConfig(rulesyncConfig, toolConfig);
218
+ configs.push({
219
+ filepath,
220
+ content: `${content}
221
+ `
222
+ });
223
+ }
224
+ return configs;
225
+ }
151
226
  function generateMcpFromRegistry(tool, config) {
152
227
  const generatorConfig = MCP_GENERATOR_REGISTRY[tool];
153
228
  if (!generatorConfig) {
@@ -155,6 +230,58 @@ function generateMcpFromRegistry(tool, config) {
155
230
  }
156
231
  return generateMcpConfig(config, generatorConfig);
157
232
  }
233
+ function generateMcpConfigurationFilesFromRegistry(tool, mcpServers, baseDir = "") {
234
+ const generatorConfig = MCP_GENERATOR_REGISTRY[tool];
235
+ if (!generatorConfig) {
236
+ throw new Error(`No MCP generator configuration found for tool: ${tool}`);
237
+ }
238
+ if (tool === "junie") {
239
+ return generateJunieMcpConfigurationFiles(mcpServers, baseDir);
240
+ }
241
+ const customTools = ["copilot", "augmentcode", "roo", "codexcli", "kiro", "geminicli"];
242
+ if (customTools.includes(tool)) {
243
+ throw new Error(
244
+ `Tool ${tool} uses custom configuration logic - use its specific generator function instead`
245
+ );
246
+ }
247
+ return generateMcpConfigurationFiles(mcpServers, generatorConfig, baseDir);
248
+ }
249
+ function generateJunieMcpConfigurationFiles(mcpServers, baseDir = "") {
250
+ const filepath = baseDir ? `${baseDir}/.junie/mcp-config.json` : ".junie/mcp-config.json";
251
+ const config = {
252
+ mcpServers: {}
253
+ };
254
+ for (const [serverName, server] of Object.entries(mcpServers)) {
255
+ if (!shouldIncludeServer(server, "junie")) {
256
+ continue;
257
+ }
258
+ const { targets: _, transport, cwd, ...serverConfig } = server;
259
+ const junieServer = {
260
+ ...serverConfig,
261
+ name: serverName
262
+ };
263
+ if (cwd) {
264
+ junieServer.workingDirectory = cwd;
265
+ }
266
+ if (transport) {
267
+ if (String(transport) === "streamable-http") {
268
+ junieServer.transport = "http";
269
+ } else if (transport === "stdio" || transport === "http" || transport === "sse") {
270
+ junieServer.transport = transport;
271
+ }
272
+ } else if (serverConfig.command) {
273
+ junieServer.transport = "stdio";
274
+ }
275
+ config.mcpServers[serverName] = junieServer;
276
+ }
277
+ return [
278
+ {
279
+ filepath,
280
+ content: `${JSON.stringify(config, null, 2)}
281
+ `
282
+ }
283
+ ];
284
+ }
158
285
  var serverTransforms, configWrappers, MCP_GENERATOR_REGISTRY;
159
286
  var init_shared_factory = __esm({
160
287
  "src/generators/mcp/shared-factory.ts"() {
@@ -231,7 +358,7 @@ var init_shared_factory = __esm({
231
358
  MCP_GENERATOR_REGISTRY = {
232
359
  claudecode: {
233
360
  target: "claudecode",
234
- configPaths: [".claude/settings.json"],
361
+ configPaths: [".mcp.json"],
235
362
  serverTransform: (server) => {
236
363
  const claudeServer = {};
237
364
  if (server.command) {
@@ -361,9 +488,17 @@ var init_shared_factory = __esm({
361
488
  });
362
489
 
363
490
  // src/generators/mcp/claudecode.ts
491
+ var claudecode_exports = {};
492
+ __export(claudecode_exports, {
493
+ generateClaudeMcp: () => generateClaudeMcp,
494
+ generateClaudeMcpConfiguration: () => generateClaudeMcpConfiguration
495
+ });
364
496
  function generateClaudeMcp(config) {
365
497
  return generateMcpFromRegistry("claudecode", config);
366
498
  }
499
+ function generateClaudeMcpConfiguration(mcpServers, baseDir = "") {
500
+ return generateMcpConfigurationFilesFromRegistry("claudecode", mcpServers, baseDir);
501
+ }
367
502
  var init_claudecode = __esm({
368
503
  "src/generators/mcp/claudecode.ts"() {
369
504
  "use strict";
@@ -372,9 +507,17 @@ var init_claudecode = __esm({
372
507
  });
373
508
 
374
509
  // src/generators/mcp/cline.ts
510
+ var cline_exports = {};
511
+ __export(cline_exports, {
512
+ generateClineMcp: () => generateClineMcp,
513
+ generateClineMcpConfiguration: () => generateClineMcpConfiguration
514
+ });
375
515
  function generateClineMcp(config) {
376
516
  return generateMcpFromRegistry("cline", config);
377
517
  }
518
+ function generateClineMcpConfiguration(mcpServers, baseDir = "") {
519
+ return generateMcpConfigurationFilesFromRegistry("cline", mcpServers, baseDir);
520
+ }
378
521
  var init_cline = __esm({
379
522
  "src/generators/mcp/cline.ts"() {
380
523
  "use strict";
@@ -383,6 +526,11 @@ var init_cline = __esm({
383
526
  });
384
527
 
385
528
  // src/generators/mcp/codexcli.ts
529
+ var codexcli_exports = {};
530
+ __export(codexcli_exports, {
531
+ generateCodexMcp: () => generateCodexMcp,
532
+ generateCodexMcpConfiguration: () => generateCodexMcpConfiguration
533
+ });
386
534
  function generateCodexMcp(config) {
387
535
  return generateMcpConfig(config, {
388
536
  target: "codexcli",
@@ -442,6 +590,81 @@ function generateCodexMcp(config) {
442
590
  })
443
591
  });
444
592
  }
593
+ function generateCodexMcpConfiguration(mcpServers, baseDir = "") {
594
+ return generateMcpConfigurationFiles(
595
+ mcpServers,
596
+ {
597
+ target: "codexcli",
598
+ configPaths: [".codex/mcp-config.json"],
599
+ serverTransform: (server) => {
600
+ const { targets: _, transport, ...serverConfig } = server;
601
+ const codexServer = {};
602
+ if (serverConfig.command !== void 0) codexServer.command = serverConfig.command;
603
+ if (serverConfig.args !== void 0) codexServer.args = serverConfig.args;
604
+ if (serverConfig.url !== void 0) codexServer.url = serverConfig.url;
605
+ if (serverConfig.httpUrl !== void 0) codexServer.httpUrl = serverConfig.httpUrl;
606
+ if (serverConfig.env !== void 0) codexServer.env = serverConfig.env;
607
+ if (serverConfig.disabled !== void 0) codexServer.disabled = serverConfig.disabled;
608
+ if (serverConfig.networkTimeout !== void 0)
609
+ codexServer.networkTimeout = serverConfig.networkTimeout;
610
+ if (serverConfig.timeout !== void 0) codexServer.timeout = serverConfig.timeout;
611
+ if (serverConfig.trust !== void 0) codexServer.trust = serverConfig.trust;
612
+ if (serverConfig.cwd !== void 0) codexServer.cwd = serverConfig.cwd;
613
+ if (serverConfig.type !== void 0) codexServer.type = serverConfig.type;
614
+ if (serverConfig.alwaysAllow !== void 0)
615
+ codexServer.alwaysAllow = serverConfig.alwaysAllow;
616
+ if (serverConfig.tools !== void 0) codexServer.tools = serverConfig.tools;
617
+ if (serverConfig.kiroAutoApprove !== void 0)
618
+ codexServer.autoApprove = serverConfig.kiroAutoApprove;
619
+ if (serverConfig.kiroAutoBlock !== void 0)
620
+ codexServer.autoBlock = serverConfig.kiroAutoBlock;
621
+ if (serverConfig.headers !== void 0) codexServer.headers = serverConfig.headers;
622
+ if (serverConfig.httpUrl !== void 0) {
623
+ codexServer.url = serverConfig.httpUrl;
624
+ delete codexServer.httpUrl;
625
+ }
626
+ if (transport) {
627
+ codexServer.transport = transport;
628
+ } else if (serverConfig.url && !serverConfig.httpUrl) {
629
+ codexServer.transport = "sse";
630
+ } else {
631
+ codexServer.transport = "stdio";
632
+ }
633
+ if (serverConfig.env) {
634
+ codexServer.env = { ...serverConfig.env };
635
+ if (!codexServer.env.CODEX_DEFAULT_MODEL) {
636
+ codexServer.env.CODEX_DEFAULT_MODEL = "gpt-4o-mini";
637
+ }
638
+ }
639
+ if (serverConfig.cwd) {
640
+ codexServer.cwd = serverConfig.cwd;
641
+ codexServer.workingDirectory = serverConfig.cwd;
642
+ }
643
+ if (serverConfig.timeout) {
644
+ codexServer.timeout = serverConfig.timeout;
645
+ }
646
+ if (serverConfig.headers) {
647
+ codexServer.headers = serverConfig.headers;
648
+ }
649
+ return codexServer;
650
+ },
651
+ configWrapper: (servers) => ({
652
+ // Configuration format for MCP wrapper servers that integrate with Codex CLI
653
+ servers,
654
+ _comment: "Configuration for MCP wrapper servers like openai-codex-mcp that integrate with Codex CLI",
655
+ _usage: "Use with third-party MCP servers that expose Codex CLI functionality to other MCP clients",
656
+ _examples: {
657
+ python_server: "python -m mcp_server or uvicorn codex_server:app",
658
+ nodejs_server: "node dist/server.js or npm start",
659
+ docker_server: "docker run -i --rm custom/codex-mcp:latest"
660
+ },
661
+ _security_note: "Store API keys in environment variables, not in this configuration file",
662
+ _supported_transports: ["stdio", "sse", "http"]
663
+ })
664
+ },
665
+ baseDir
666
+ );
667
+ }
445
668
  var init_codexcli = __esm({
446
669
  "src/generators/mcp/codexcli.ts"() {
447
670
  "use strict";
@@ -450,6 +673,11 @@ var init_codexcli = __esm({
450
673
  });
451
674
 
452
675
  // src/generators/mcp/copilot.ts
676
+ var copilot_exports = {};
677
+ __export(copilot_exports, {
678
+ generateCopilotMcp: () => generateCopilotMcp,
679
+ generateCopilotMcpConfiguration: () => generateCopilotMcpConfiguration
680
+ });
453
681
  function generateCopilotMcp(config, target) {
454
682
  const servers = {};
455
683
  const inputs = [];
@@ -501,6 +729,23 @@ function generateCopilotMcp(config, target) {
501
729
  return JSON.stringify(config2, null, 2);
502
730
  }
503
731
  }
732
+ function generateCopilotMcpConfiguration(mcpServers, baseDir = "") {
733
+ const configs = [];
734
+ const rulesyncConfig = { mcpServers };
735
+ const editorContent = generateCopilotMcp(rulesyncConfig, "editor");
736
+ configs.push({
737
+ filepath: baseDir ? `${baseDir}/.vscode/mcp.json` : ".vscode/mcp.json",
738
+ content: `${editorContent}
739
+ `
740
+ });
741
+ const codingAgentContent = generateCopilotMcp(rulesyncConfig, "codingAgent");
742
+ configs.push({
743
+ filepath: baseDir ? `${baseDir}/.copilot/mcp.json` : ".copilot/mcp.json",
744
+ content: `${codingAgentContent}
745
+ `
746
+ });
747
+ return configs;
748
+ }
504
749
  var init_copilot = __esm({
505
750
  "src/generators/mcp/copilot.ts"() {
506
751
  "use strict";
@@ -509,9 +754,17 @@ var init_copilot = __esm({
509
754
  });
510
755
 
511
756
  // src/generators/mcp/cursor.ts
757
+ var cursor_exports = {};
758
+ __export(cursor_exports, {
759
+ generateCursorMcp: () => generateCursorMcp,
760
+ generateCursorMcpConfiguration: () => generateCursorMcpConfiguration
761
+ });
512
762
  function generateCursorMcp(config) {
513
763
  return generateMcpFromRegistry("cursor", config);
514
764
  }
765
+ function generateCursorMcpConfiguration(mcpServers, baseDir = "") {
766
+ return generateMcpConfigurationFilesFromRegistry("cursor", mcpServers, baseDir);
767
+ }
515
768
  var init_cursor = __esm({
516
769
  "src/generators/mcp/cursor.ts"() {
517
770
  "use strict";
@@ -520,6 +773,11 @@ var init_cursor = __esm({
520
773
  });
521
774
 
522
775
  // src/generators/mcp/geminicli.ts
776
+ var geminicli_exports = {};
777
+ __export(geminicli_exports, {
778
+ generateGeminiCliMcp: () => generateGeminiCliMcp,
779
+ generateGeminiCliMcpConfiguration: () => generateGeminiCliMcpConfiguration
780
+ });
523
781
  function generateGeminiCliMcp(config) {
524
782
  return generateMcpConfig(config, {
525
783
  target: "geminicli",
@@ -550,6 +808,25 @@ function generateGeminiCliMcp(config) {
550
808
  configWrapper: configWrappers.mcpServers
551
809
  });
552
810
  }
811
+ function generateGeminiCliMcpConfiguration(mcpServers, baseDir = "") {
812
+ return generateMcpConfigurationFiles(
813
+ mcpServers,
814
+ {
815
+ target: "geminicli",
816
+ configPaths: [".gemini/settings.json"],
817
+ serverTransform: (server) => {
818
+ const { targets: _, ...serverConfig } = server;
819
+ const geminiServer = { ...serverConfig };
820
+ if (server.env) {
821
+ geminiServer.env = server.env;
822
+ }
823
+ return geminiServer;
824
+ },
825
+ configWrapper: configWrappers.mcpServers
826
+ },
827
+ baseDir
828
+ );
829
+ }
553
830
  var init_geminicli = __esm({
554
831
  "src/generators/mcp/geminicli.ts"() {
555
832
  "use strict";
@@ -558,9 +835,17 @@ var init_geminicli = __esm({
558
835
  });
559
836
 
560
837
  // src/generators/mcp/junie.ts
838
+ var junie_exports = {};
839
+ __export(junie_exports, {
840
+ generateJunieMcp: () => generateJunieMcp,
841
+ generateJunieMcpConfiguration: () => generateJunieMcpConfiguration
842
+ });
561
843
  function generateJunieMcp(config) {
562
844
  return generateMcpFromRegistry("junie", config);
563
845
  }
846
+ function generateJunieMcpConfiguration(mcpServers, baseDir = "") {
847
+ return generateMcpConfigurationFilesFromRegistry("junie", mcpServers, baseDir);
848
+ }
564
849
  var init_junie = __esm({
565
850
  "src/generators/mcp/junie.ts"() {
566
851
  "use strict";
@@ -569,6 +854,11 @@ var init_junie = __esm({
569
854
  });
570
855
 
571
856
  // src/generators/mcp/kiro.ts
857
+ var kiro_exports = {};
858
+ __export(kiro_exports, {
859
+ generateKiroMcp: () => generateKiroMcp,
860
+ generateKiroMcpConfiguration: () => generateKiroMcpConfiguration
861
+ });
572
862
  function generateKiroMcp(config) {
573
863
  const kiroConfig = {
574
864
  mcpServers: {}
@@ -612,6 +902,39 @@ function generateKiroMcp(config) {
612
902
  }
613
903
  return JSON.stringify(kiroConfig, null, 2);
614
904
  }
905
+ function generateKiroMcpConfiguration(mcpServers, baseDir = "") {
906
+ const filepath = baseDir ? `${baseDir}/.kiro/mcp.json` : ".kiro/mcp.json";
907
+ const config = {
908
+ mcpServers: {}
909
+ };
910
+ for (const [serverName, server] of Object.entries(mcpServers)) {
911
+ if (!shouldIncludeServer(server, "kiro")) {
912
+ continue;
913
+ }
914
+ const { targets: _targets, ...serverConfig } = server;
915
+ const kiroServer = { ...serverConfig };
916
+ if (serverConfig.httpUrl !== void 0) {
917
+ kiroServer.url = serverConfig.httpUrl;
918
+ delete kiroServer.httpUrl;
919
+ }
920
+ if (serverConfig.kiroAutoApprove !== void 0) {
921
+ kiroServer.autoApprove = serverConfig.kiroAutoApprove;
922
+ delete kiroServer.kiroAutoApprove;
923
+ }
924
+ if (serverConfig.kiroAutoBlock !== void 0) {
925
+ kiroServer.autoBlock = serverConfig.kiroAutoBlock;
926
+ delete kiroServer.kiroAutoBlock;
927
+ }
928
+ config.mcpServers[serverName] = kiroServer;
929
+ }
930
+ return [
931
+ {
932
+ filepath,
933
+ content: `${JSON.stringify(config, null, 2)}
934
+ `
935
+ }
936
+ ];
937
+ }
615
938
  var init_kiro = __esm({
616
939
  "src/generators/mcp/kiro.ts"() {
617
940
  "use strict";
@@ -620,6 +943,11 @@ var init_kiro = __esm({
620
943
  });
621
944
 
622
945
  // src/generators/mcp/roo.ts
946
+ var roo_exports = {};
947
+ __export(roo_exports, {
948
+ generateRooMcp: () => generateRooMcp,
949
+ generateRooMcpConfiguration: () => generateRooMcpConfiguration
950
+ });
623
951
  function generateRooMcp(config) {
624
952
  const rooConfig = {
625
953
  mcpServers: {}
@@ -664,6 +992,30 @@ function generateRooMcp(config) {
664
992
  }
665
993
  return JSON.stringify(rooConfig, null, 2);
666
994
  }
995
+ function generateRooMcpConfiguration(mcpServers, baseDir = "") {
996
+ const filepath = baseDir ? `${baseDir}/.roo/mcp.json` : ".roo/mcp.json";
997
+ const config = {
998
+ mcpServers: {}
999
+ };
1000
+ for (const [serverName, server] of Object.entries(mcpServers)) {
1001
+ if (!shouldIncludeServer(server, "roo")) {
1002
+ continue;
1003
+ }
1004
+ const { targets: _targets, ...serverConfig } = server;
1005
+ const rooServer = { ...serverConfig };
1006
+ if (serverConfig.httpUrl !== void 0 && serverConfig.url !== void 0) {
1007
+ rooServer.url = serverConfig.httpUrl;
1008
+ }
1009
+ config.mcpServers[serverName] = rooServer;
1010
+ }
1011
+ return [
1012
+ {
1013
+ filepath,
1014
+ content: `${JSON.stringify(config, null, 2)}
1015
+ `
1016
+ }
1017
+ ];
1018
+ }
667
1019
  var init_roo = __esm({
668
1020
  "src/generators/mcp/roo.ts"() {
669
1021
  "use strict";
@@ -672,9 +1024,17 @@ var init_roo = __esm({
672
1024
  });
673
1025
 
674
1026
  // src/generators/mcp/windsurf.ts
1027
+ var windsurf_exports = {};
1028
+ __export(windsurf_exports, {
1029
+ generateWindsurfMcp: () => generateWindsurfMcp,
1030
+ generateWindsurfMcpConfiguration: () => generateWindsurfMcpConfiguration
1031
+ });
675
1032
  function generateWindsurfMcp(config) {
676
1033
  return generateMcpFromRegistry("windsurf", config);
677
1034
  }
1035
+ function generateWindsurfMcpConfiguration(mcpServers, baseDir = "") {
1036
+ return generateMcpConfigurationFilesFromRegistry("windsurf", mcpServers, baseDir);
1037
+ }
678
1038
  var init_windsurf = __esm({
679
1039
  "src/generators/mcp/windsurf.ts"() {
680
1040
  "use strict";
@@ -771,132 +1131,141 @@ var ClaudeSettingsSchema = import_mini2.z.looseObject({
771
1131
  )
772
1132
  });
773
1133
 
774
- // src/types/config.ts
1134
+ // src/types/commands.ts
775
1135
  var import_mini3 = require("zod/mini");
1136
+ var CommandFrontmatterSchema = import_mini3.z.object({
1137
+ description: import_mini3.z.optional(import_mini3.z.string())
1138
+ });
1139
+
1140
+ // src/types/config.ts
1141
+ var import_mini4 = require("zod/mini");
776
1142
  init_tool_targets();
777
- var ConfigSchema = import_mini3.z.object({
778
- aiRulesDir: import_mini3.z.string(),
779
- outputPaths: import_mini3.z.record(ToolTargetSchema, import_mini3.z.string()),
780
- watchEnabled: import_mini3.z.boolean(),
781
- defaultTargets: ToolTargetsSchema
1143
+ var ConfigSchema = import_mini4.z.object({
1144
+ aiRulesDir: import_mini4.z.string(),
1145
+ outputPaths: import_mini4.z.record(ToolTargetSchema, import_mini4.z.string()),
1146
+ watchEnabled: import_mini4.z.boolean(),
1147
+ defaultTargets: ToolTargetsSchema,
1148
+ claudecodeCommands: import_mini4.z.optional(import_mini4.z.string()),
1149
+ geminicliCommands: import_mini4.z.optional(import_mini4.z.string())
782
1150
  });
783
1151
 
784
1152
  // src/types/config-options.ts
785
- var import_mini4 = require("zod/mini");
1153
+ var import_mini5 = require("zod/mini");
786
1154
  init_tool_targets();
787
- var OutputPathsSchema = import_mini4.z.object({
788
- augmentcode: import_mini4.z.optional(import_mini4.z.string()),
789
- "augmentcode-legacy": import_mini4.z.optional(import_mini4.z.string()),
790
- copilot: import_mini4.z.optional(import_mini4.z.string()),
791
- cursor: import_mini4.z.optional(import_mini4.z.string()),
792
- cline: import_mini4.z.optional(import_mini4.z.string()),
793
- claudecode: import_mini4.z.optional(import_mini4.z.string()),
794
- codexcli: import_mini4.z.optional(import_mini4.z.string()),
795
- roo: import_mini4.z.optional(import_mini4.z.string()),
796
- geminicli: import_mini4.z.optional(import_mini4.z.string()),
797
- kiro: import_mini4.z.optional(import_mini4.z.string()),
798
- junie: import_mini4.z.optional(import_mini4.z.string()),
799
- windsurf: import_mini4.z.optional(import_mini4.z.string())
1155
+ var OutputPathsSchema = import_mini5.z.object({
1156
+ augmentcode: import_mini5.z.optional(import_mini5.z.string()),
1157
+ "augmentcode-legacy": import_mini5.z.optional(import_mini5.z.string()),
1158
+ copilot: import_mini5.z.optional(import_mini5.z.string()),
1159
+ cursor: import_mini5.z.optional(import_mini5.z.string()),
1160
+ cline: import_mini5.z.optional(import_mini5.z.string()),
1161
+ claudecode: import_mini5.z.optional(import_mini5.z.string()),
1162
+ codexcli: import_mini5.z.optional(import_mini5.z.string()),
1163
+ roo: import_mini5.z.optional(import_mini5.z.string()),
1164
+ geminicli: import_mini5.z.optional(import_mini5.z.string()),
1165
+ kiro: import_mini5.z.optional(import_mini5.z.string()),
1166
+ junie: import_mini5.z.optional(import_mini5.z.string()),
1167
+ windsurf: import_mini5.z.optional(import_mini5.z.string())
800
1168
  });
801
- var ConfigOptionsSchema = import_mini4.z.object({
802
- aiRulesDir: import_mini4.z.optional(import_mini4.z.string()),
803
- outputPaths: import_mini4.z.optional(OutputPathsSchema),
804
- watchEnabled: import_mini4.z.optional(import_mini4.z.boolean()),
805
- defaultTargets: import_mini4.z.optional(ToolTargetsSchema),
806
- targets: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
807
- exclude: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
808
- verbose: import_mini4.z.optional(import_mini4.z.boolean()),
809
- delete: import_mini4.z.optional(import_mini4.z.boolean()),
810
- baseDir: import_mini4.z.optional(import_mini4.z.union([import_mini4.z.string(), import_mini4.z.array(import_mini4.z.string())])),
811
- watch: import_mini4.z.optional(
812
- import_mini4.z.object({
813
- enabled: import_mini4.z.optional(import_mini4.z.boolean()),
814
- interval: import_mini4.z.optional(import_mini4.z.number()),
815
- ignore: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string()))
1169
+ var ConfigOptionsSchema = import_mini5.z.object({
1170
+ aiRulesDir: import_mini5.z.optional(import_mini5.z.string()),
1171
+ outputPaths: import_mini5.z.optional(OutputPathsSchema),
1172
+ watchEnabled: import_mini5.z.optional(import_mini5.z.boolean()),
1173
+ defaultTargets: import_mini5.z.optional(ToolTargetsSchema),
1174
+ targets: import_mini5.z.optional(import_mini5.z.array(ToolTargetSchema)),
1175
+ exclude: import_mini5.z.optional(import_mini5.z.array(ToolTargetSchema)),
1176
+ verbose: import_mini5.z.optional(import_mini5.z.boolean()),
1177
+ delete: import_mini5.z.optional(import_mini5.z.boolean()),
1178
+ baseDir: import_mini5.z.optional(import_mini5.z.union([import_mini5.z.string(), import_mini5.z.array(import_mini5.z.string())])),
1179
+ watch: import_mini5.z.optional(
1180
+ import_mini5.z.object({
1181
+ enabled: import_mini5.z.optional(import_mini5.z.boolean()),
1182
+ interval: import_mini5.z.optional(import_mini5.z.number()),
1183
+ ignore: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string()))
816
1184
  })
817
1185
  )
818
1186
  });
819
- var MergedConfigSchema = import_mini4.z.object({
820
- aiRulesDir: import_mini4.z.string(),
821
- outputPaths: import_mini4.z.record(ToolTargetSchema, import_mini4.z.string()),
822
- watchEnabled: import_mini4.z.boolean(),
1187
+ var MergedConfigSchema = import_mini5.z.object({
1188
+ aiRulesDir: import_mini5.z.string(),
1189
+ outputPaths: import_mini5.z.record(ToolTargetSchema, import_mini5.z.string()),
1190
+ watchEnabled: import_mini5.z.boolean(),
823
1191
  defaultTargets: ToolTargetsSchema,
824
- targets: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
825
- exclude: import_mini4.z.optional(import_mini4.z.array(ToolTargetSchema)),
826
- verbose: import_mini4.z.optional(import_mini4.z.boolean()),
827
- delete: import_mini4.z.optional(import_mini4.z.boolean()),
828
- baseDir: import_mini4.z.optional(import_mini4.z.union([import_mini4.z.string(), import_mini4.z.array(import_mini4.z.string())])),
829
- configPath: import_mini4.z.optional(import_mini4.z.string()),
830
- watch: import_mini4.z.optional(
831
- import_mini4.z.object({
832
- enabled: import_mini4.z.optional(import_mini4.z.boolean()),
833
- interval: import_mini4.z.optional(import_mini4.z.number()),
834
- ignore: import_mini4.z.optional(import_mini4.z.array(import_mini4.z.string()))
1192
+ targets: import_mini5.z.optional(import_mini5.z.array(ToolTargetSchema)),
1193
+ exclude: import_mini5.z.optional(import_mini5.z.array(ToolTargetSchema)),
1194
+ verbose: import_mini5.z.optional(import_mini5.z.boolean()),
1195
+ delete: import_mini5.z.optional(import_mini5.z.boolean()),
1196
+ baseDir: import_mini5.z.optional(import_mini5.z.union([import_mini5.z.string(), import_mini5.z.array(import_mini5.z.string())])),
1197
+ configPath: import_mini5.z.optional(import_mini5.z.string()),
1198
+ watch: import_mini5.z.optional(
1199
+ import_mini5.z.object({
1200
+ enabled: import_mini5.z.optional(import_mini5.z.boolean()),
1201
+ interval: import_mini5.z.optional(import_mini5.z.number()),
1202
+ ignore: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string()))
835
1203
  })
836
1204
  )
837
1205
  });
838
1206
 
839
1207
  // src/types/mcp.ts
840
- var import_mini5 = require("zod/mini");
1208
+ var import_mini6 = require("zod/mini");
841
1209
  init_tool_targets();
842
- var McpTransportTypeSchema = import_mini5.z.enum(["stdio", "sse", "http"]);
843
- var McpServerBaseSchema = import_mini5.z.object({
844
- command: import_mini5.z.optional(import_mini5.z.string()),
845
- args: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
846
- url: import_mini5.z.optional(import_mini5.z.string()),
847
- httpUrl: import_mini5.z.optional(import_mini5.z.string()),
848
- env: import_mini5.z.optional(import_mini5.z.record(import_mini5.z.string(), import_mini5.z.string())),
849
- disabled: import_mini5.z.optional(import_mini5.z.boolean()),
850
- networkTimeout: import_mini5.z.optional(import_mini5.z.number()),
851
- timeout: import_mini5.z.optional(import_mini5.z.number()),
852
- trust: import_mini5.z.optional(import_mini5.z.boolean()),
853
- cwd: import_mini5.z.optional(import_mini5.z.string()),
854
- transport: import_mini5.z.optional(McpTransportTypeSchema),
855
- type: import_mini5.z.optional(import_mini5.z.enum(["sse", "streamable-http"])),
856
- alwaysAllow: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
857
- tools: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
858
- kiroAutoApprove: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
859
- kiroAutoBlock: import_mini5.z.optional(import_mini5.z.array(import_mini5.z.string())),
860
- headers: import_mini5.z.optional(import_mini5.z.record(import_mini5.z.string(), import_mini5.z.string()))
1210
+ var McpTransportTypeSchema = import_mini6.z.enum(["stdio", "sse", "http"]);
1211
+ var McpServerBaseSchema = import_mini6.z.object({
1212
+ command: import_mini6.z.optional(import_mini6.z.string()),
1213
+ args: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
1214
+ url: import_mini6.z.optional(import_mini6.z.string()),
1215
+ httpUrl: import_mini6.z.optional(import_mini6.z.string()),
1216
+ env: import_mini6.z.optional(import_mini6.z.record(import_mini6.z.string(), import_mini6.z.string())),
1217
+ disabled: import_mini6.z.optional(import_mini6.z.boolean()),
1218
+ networkTimeout: import_mini6.z.optional(import_mini6.z.number()),
1219
+ timeout: import_mini6.z.optional(import_mini6.z.number()),
1220
+ trust: import_mini6.z.optional(import_mini6.z.boolean()),
1221
+ cwd: import_mini6.z.optional(import_mini6.z.string()),
1222
+ transport: import_mini6.z.optional(McpTransportTypeSchema),
1223
+ type: import_mini6.z.optional(import_mini6.z.enum(["sse", "streamable-http"])),
1224
+ alwaysAllow: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
1225
+ tools: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
1226
+ kiroAutoApprove: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
1227
+ kiroAutoBlock: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
1228
+ headers: import_mini6.z.optional(import_mini6.z.record(import_mini6.z.string(), import_mini6.z.string()))
861
1229
  });
862
- var RulesyncMcpServerSchema = import_mini5.z.extend(McpServerBaseSchema, {
863
- targets: import_mini5.z.optional(RulesyncTargetsSchema)
1230
+ var RulesyncMcpServerSchema = import_mini6.z.extend(McpServerBaseSchema, {
1231
+ targets: import_mini6.z.optional(RulesyncTargetsSchema)
864
1232
  });
865
- var McpConfigSchema = import_mini5.z.object({
866
- mcpServers: import_mini5.z.record(import_mini5.z.string(), McpServerBaseSchema)
1233
+ var McpConfigSchema = import_mini6.z.object({
1234
+ mcpServers: import_mini6.z.record(import_mini6.z.string(), McpServerBaseSchema)
867
1235
  });
868
- var RulesyncMcpConfigSchema = import_mini5.z.object({
869
- mcpServers: import_mini5.z.record(import_mini5.z.string(), RulesyncMcpServerSchema)
1236
+ var RulesyncMcpConfigSchema = import_mini6.z.object({
1237
+ mcpServers: import_mini6.z.record(import_mini6.z.string(), RulesyncMcpServerSchema)
870
1238
  });
871
1239
 
872
1240
  // src/types/rules.ts
873
- var import_mini6 = require("zod/mini");
1241
+ var import_mini7 = require("zod/mini");
874
1242
  init_tool_targets();
875
- var RuleFrontmatterSchema = import_mini6.z.object({
876
- root: import_mini6.z.optional(import_mini6.z.boolean()),
877
- targets: import_mini6.z.optional(RulesyncTargetsSchema),
878
- description: import_mini6.z.optional(import_mini6.z.string()),
879
- globs: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string())),
880
- cursorRuleType: import_mini6.z.optional(import_mini6.z.enum(["always", "manual", "specificFiles", "intelligently"])),
881
- windsurfActivationMode: import_mini6.z.optional(import_mini6.z.enum(["always", "manual", "model-decision", "glob"])),
882
- windsurfOutputFormat: import_mini6.z.optional(import_mini6.z.enum(["single-file", "directory"])),
883
- tags: import_mini6.z.optional(import_mini6.z.array(import_mini6.z.string()))
1243
+ var RuleFrontmatterSchema = import_mini7.z.object({
1244
+ root: import_mini7.z.optional(import_mini7.z.boolean()),
1245
+ targets: import_mini7.z.optional(RulesyncTargetsSchema),
1246
+ description: import_mini7.z.optional(import_mini7.z.string()),
1247
+ globs: import_mini7.z.optional(import_mini7.z.array(import_mini7.z.string())),
1248
+ cursorRuleType: import_mini7.z.optional(import_mini7.z.enum(["always", "manual", "specificFiles", "intelligently"])),
1249
+ windsurfActivationMode: import_mini7.z.optional(import_mini7.z.enum(["always", "manual", "model-decision", "glob"])),
1250
+ windsurfOutputFormat: import_mini7.z.optional(import_mini7.z.enum(["single-file", "directory"])),
1251
+ tags: import_mini7.z.optional(import_mini7.z.array(import_mini7.z.string()))
884
1252
  });
885
- var ParsedRuleSchema = import_mini6.z.object({
1253
+ var ParsedRuleSchema = import_mini7.z.object({
886
1254
  frontmatter: RuleFrontmatterSchema,
887
- content: import_mini6.z.string(),
888
- filename: import_mini6.z.string(),
889
- filepath: import_mini6.z.string()
1255
+ content: import_mini7.z.string(),
1256
+ filename: import_mini7.z.string(),
1257
+ filepath: import_mini7.z.string(),
1258
+ type: import_mini7.z.optional(import_mini7.z.enum(["rule", "command"]))
890
1259
  });
891
- var GeneratedOutputSchema = import_mini6.z.object({
1260
+ var GeneratedOutputSchema = import_mini7.z.object({
892
1261
  tool: ToolTargetSchema,
893
- filepath: import_mini6.z.string(),
894
- content: import_mini6.z.string()
1262
+ filepath: import_mini7.z.string(),
1263
+ content: import_mini7.z.string()
895
1264
  });
896
- var GenerateOptionsSchema = import_mini6.z.object({
897
- targetTools: import_mini6.z.optional(ToolTargetsSchema),
898
- outputDir: import_mini6.z.optional(import_mini6.z.string()),
899
- watch: import_mini6.z.optional(import_mini6.z.boolean())
1265
+ var GenerateOptionsSchema = import_mini7.z.object({
1266
+ targetTools: import_mini7.z.optional(ToolTargetsSchema),
1267
+ outputDir: import_mini7.z.optional(import_mini7.z.string()),
1268
+ watch: import_mini7.z.optional(import_mini7.z.boolean())
900
1269
  });
901
1270
 
902
1271
  // src/types/index.ts
@@ -1191,28 +1560,6 @@ async function removeClaudeGeneratedFiles() {
1191
1560
  }
1192
1561
  }
1193
1562
 
1194
- // src/utils/rules.ts
1195
- function isToolSpecificRule(rule, targetTool) {
1196
- const filename = rule.filename;
1197
- const toolPatterns = {
1198
- "augmentcode-legacy": /^specification-augmentcode-legacy-/i,
1199
- augmentcode: /^specification-augmentcode-/i,
1200
- copilot: /^specification-copilot-/i,
1201
- cursor: /^specification-cursor-/i,
1202
- cline: /^specification-cline-/i,
1203
- claudecode: /^specification-claudecode-/i,
1204
- roo: /^specification-roo-/i,
1205
- geminicli: /^specification-geminicli-/i,
1206
- kiro: /^specification-kiro-/i
1207
- };
1208
- for (const [tool, pattern] of Object.entries(toolPatterns)) {
1209
- if (pattern.test(filename)) {
1210
- return tool === targetTool;
1211
- }
1212
- }
1213
- return true;
1214
- }
1215
-
1216
1563
  // src/cli/commands/config.ts
1217
1564
  async function configCommand(options = {}) {
1218
1565
  if (options.init) {
@@ -1424,10 +1771,165 @@ export default config;
1424
1771
  }
1425
1772
 
1426
1773
  // src/cli/commands/generate.ts
1427
- var import_node_path10 = require("path");
1774
+ var import_node_path14 = require("path");
1428
1775
 
1429
- // src/generators/ignore/shared-factory.ts
1776
+ // src/core/command-generator.ts
1777
+ var import_node_path6 = require("path");
1778
+
1779
+ // src/generators/commands/claudecode.ts
1430
1780
  var import_node_path3 = require("path");
1781
+ var ClaudeCodeCommandGenerator = class {
1782
+ generate(command, outputDir) {
1783
+ const filepath = this.getOutputPath(command.filename, outputDir);
1784
+ const frontmatter = ["---"];
1785
+ if (command.frontmatter.description) {
1786
+ frontmatter.push(`description: ${command.frontmatter.description}`);
1787
+ }
1788
+ frontmatter.push("---");
1789
+ const content = `${frontmatter.join("\n")}
1790
+
1791
+ ${command.content.trim()}
1792
+ `;
1793
+ return {
1794
+ tool: "claudecode",
1795
+ filepath,
1796
+ content
1797
+ };
1798
+ }
1799
+ getOutputPath(filename, baseDir) {
1800
+ const flattenedName = filename.replace(/\//g, "-");
1801
+ return (0, import_node_path3.join)(baseDir, ".claude", "commands", `${flattenedName}.md`);
1802
+ }
1803
+ };
1804
+
1805
+ // src/generators/commands/geminicli.ts
1806
+ var import_node_path4 = require("path");
1807
+ var GeminiCliCommandGenerator = class {
1808
+ generate(command, outputDir) {
1809
+ const filepath = this.getOutputPath(command.filename, outputDir);
1810
+ const convertedContent = this.convertSyntax(command.content);
1811
+ const tomlLines = [];
1812
+ if (command.frontmatter.description) {
1813
+ tomlLines.push(`description = "${this.escapeTomlString(command.frontmatter.description)}"`);
1814
+ tomlLines.push("");
1815
+ }
1816
+ tomlLines.push(`prompt = """${convertedContent}"""`);
1817
+ const content = tomlLines.join("\n") + "\n";
1818
+ return {
1819
+ tool: "geminicli",
1820
+ filepath,
1821
+ content
1822
+ };
1823
+ }
1824
+ getOutputPath(filename, baseDir) {
1825
+ const tomlFilename = filename.replace(/\.md$/, ".toml");
1826
+ const filenameWithExt = tomlFilename.endsWith(".toml") ? tomlFilename : `${tomlFilename}.toml`;
1827
+ return (0, import_node_path4.join)(baseDir, ".gemini", "commands", filenameWithExt);
1828
+ }
1829
+ convertSyntax(content) {
1830
+ let converted = content;
1831
+ converted = converted.replace(/\$ARGUMENTS/g, "{{args}}");
1832
+ converted = converted.replace(/!`([^`]+)`/g, "!{$1}");
1833
+ const atSyntaxMatches = converted.match(/@[^\s]+/g);
1834
+ if (atSyntaxMatches) {
1835
+ console.warn(
1836
+ `\u26A0\uFE0F Warning: @ syntax found (${atSyntaxMatches.join(", ")}). Gemini CLI does not support file content injection. Consider using shell commands or remove these references.`
1837
+ );
1838
+ }
1839
+ return converted.trim();
1840
+ }
1841
+ escapeTomlString(str) {
1842
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
1843
+ }
1844
+ };
1845
+
1846
+ // src/generators/commands/index.ts
1847
+ var commandGenerators = {
1848
+ claudecode: new ClaudeCodeCommandGenerator(),
1849
+ geminicli: new GeminiCliCommandGenerator()
1850
+ };
1851
+ function getCommandGenerator(tool) {
1852
+ return commandGenerators[tool];
1853
+ }
1854
+
1855
+ // src/core/command-parser.ts
1856
+ var import_node_path5 = require("path");
1857
+ var import_gray_matter = __toESM(require("gray-matter"), 1);
1858
+ async function parseCommandsFromDirectory(commandsDir) {
1859
+ const commandFiles = await findFiles(commandsDir, ".md");
1860
+ const commands = [];
1861
+ const errors = [];
1862
+ for (const filepath of commandFiles) {
1863
+ try {
1864
+ const command = await parseCommandFile(filepath);
1865
+ commands.push(command);
1866
+ } catch (error) {
1867
+ const errorMessage = error instanceof Error ? error.message : String(error);
1868
+ errors.push(`Failed to parse command file ${filepath}: ${errorMessage}`);
1869
+ }
1870
+ }
1871
+ if (errors.length > 0) {
1872
+ console.warn(`\u26A0\uFE0F Command parsing errors:
1873
+ ${errors.join("\n")}`);
1874
+ }
1875
+ return commands;
1876
+ }
1877
+ async function parseCommandFile(filepath) {
1878
+ const content = await readFileContent(filepath);
1879
+ const parsed = (0, import_gray_matter.default)(content);
1880
+ try {
1881
+ const validatedData = CommandFrontmatterSchema.parse(parsed.data);
1882
+ const filename = (0, import_node_path5.basename)(filepath, ".md");
1883
+ return {
1884
+ frontmatter: {
1885
+ description: validatedData.description
1886
+ },
1887
+ content: parsed.content,
1888
+ filename,
1889
+ filepath
1890
+ };
1891
+ } catch (error) {
1892
+ throw new Error(
1893
+ `Invalid frontmatter in ${filepath}: ${error instanceof Error ? error.message : String(error)}`
1894
+ );
1895
+ }
1896
+ }
1897
+
1898
+ // src/core/command-generator.ts
1899
+ async function generateCommands(projectRoot, baseDir, targets) {
1900
+ const commandsDir = (0, import_node_path6.join)(projectRoot, ".rulesync", "commands");
1901
+ if (!await fileExists(commandsDir)) {
1902
+ return [];
1903
+ }
1904
+ const commands = await parseCommandsFromDirectory(commandsDir);
1905
+ if (commands.length === 0) {
1906
+ return [];
1907
+ }
1908
+ const outputs = [];
1909
+ const outputDir = baseDir || projectRoot;
1910
+ const supportedTargets = targets.filter((target) => ["claudecode", "geminicli"].includes(target));
1911
+ for (const target of supportedTargets) {
1912
+ const generator = getCommandGenerator(target);
1913
+ if (!generator) {
1914
+ continue;
1915
+ }
1916
+ for (const command of commands) {
1917
+ try {
1918
+ const output = generator.generate(command, outputDir);
1919
+ outputs.push(output);
1920
+ } catch (error) {
1921
+ const errorMessage = error instanceof Error ? error.message : String(error);
1922
+ console.error(
1923
+ `\u274C Failed to generate ${target} command for ${command.filename}: ${errorMessage}`
1924
+ );
1925
+ }
1926
+ }
1927
+ }
1928
+ return outputs;
1929
+ }
1930
+
1931
+ // src/generators/ignore/shared-factory.ts
1932
+ var import_node_path7 = require("path");
1431
1933
 
1432
1934
  // src/generators/ignore/shared-helpers.ts
1433
1935
  function extractIgnorePatternsFromRules(rules) {
@@ -1545,7 +2047,7 @@ function generateIgnoreFile(rules, config, ignoreConfig, baseDir) {
1545
2047
  const outputs = [];
1546
2048
  const content = generateIgnoreContent(rules, ignoreConfig);
1547
2049
  const outputPath = baseDir || process.cwd();
1548
- const filepath = (0, import_node_path3.join)(outputPath, ignoreConfig.filename);
2050
+ const filepath = (0, import_node_path7.join)(outputPath, ignoreConfig.filename);
1549
2051
  outputs.push({
1550
2052
  tool: ignoreConfig.tool,
1551
2053
  filepath,
@@ -2133,20 +2635,20 @@ function generateWindsurfIgnore(rules, config, baseDir) {
2133
2635
  }
2134
2636
 
2135
2637
  // src/generators/rules/augmentcode.ts
2136
- var import_node_path6 = require("path");
2638
+ var import_node_path10 = require("path");
2137
2639
 
2138
2640
  // src/generators/rules/shared-helpers.ts
2139
- var import_node_path5 = require("path");
2641
+ var import_node_path9 = require("path");
2140
2642
 
2141
2643
  // src/utils/ignore.ts
2142
- var import_node_path4 = require("path");
2644
+ var import_node_path8 = require("path");
2143
2645
  var import_micromatch = __toESM(require("micromatch"), 1);
2144
2646
  var cachedIgnorePatterns = null;
2145
2647
  async function loadIgnorePatterns(baseDir = process.cwd()) {
2146
2648
  if (cachedIgnorePatterns) {
2147
2649
  return cachedIgnorePatterns;
2148
2650
  }
2149
- const ignorePath = (0, import_node_path4.join)(baseDir, ".rulesyncignore");
2651
+ const ignorePath = (0, import_node_path8.join)(baseDir, ".rulesyncignore");
2150
2652
  if (!await fileExists(ignorePath)) {
2151
2653
  cachedIgnorePatterns = { patterns: [] };
2152
2654
  return cachedIgnorePatterns;
@@ -2200,7 +2702,7 @@ function addOutput(outputs, tool, config, baseDir, relativePath, content) {
2200
2702
  const outputDir = resolveOutputDir(config, tool, baseDir);
2201
2703
  outputs.push({
2202
2704
  tool,
2203
- filepath: (0, import_node_path5.join)(outputDir, relativePath),
2705
+ filepath: (0, import_node_path9.join)(outputDir, relativePath),
2204
2706
  content
2205
2707
  });
2206
2708
  }
@@ -2209,7 +2711,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
2209
2711
  for (const rule of rules) {
2210
2712
  const content = generatorConfig.generateContent(rule);
2211
2713
  const outputDir = resolveOutputDir(config, generatorConfig.tool, baseDir);
2212
- const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : (0, import_node_path5.join)(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
2714
+ const filepath = generatorConfig.pathResolver ? generatorConfig.pathResolver(rule, outputDir) : (0, import_node_path9.join)(outputDir, `${rule.filename}${generatorConfig.fileExtension}`);
2213
2715
  outputs.push({
2214
2716
  tool: generatorConfig.tool,
2215
2717
  filepath,
@@ -2217,7 +2719,7 @@ async function generateRulesConfig(rules, config, generatorConfig, baseDir) {
2217
2719
  });
2218
2720
  }
2219
2721
  const ignorePatterns = await loadIgnorePatterns(baseDir);
2220
- if (ignorePatterns.patterns.length > 0) {
2722
+ if (ignorePatterns.patterns.length > 0 && generatorConfig.ignoreFileName) {
2221
2723
  const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
2222
2724
  const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
2223
2725
  outputs.push({
@@ -2237,7 +2739,7 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
2237
2739
  for (const rule of detailRules) {
2238
2740
  const content = generatorConfig.generateDetailContent(rule);
2239
2741
  const filepath = resolvePath(
2240
- (0, import_node_path5.join)(generatorConfig.detailSubDir, `${rule.filename}.md`),
2742
+ (0, import_node_path9.join)(generatorConfig.detailSubDir, `${rule.filename}.md`),
2241
2743
  baseDir
2242
2744
  );
2243
2745
  outputs.push({
@@ -2258,13 +2760,15 @@ async function generateComplexRules(rules, config, generatorConfig, baseDir) {
2258
2760
  }
2259
2761
  const ignorePatterns = await loadIgnorePatterns(baseDir);
2260
2762
  if (ignorePatterns.patterns.length > 0) {
2261
- const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
2262
- const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
2263
- outputs.push({
2264
- tool: generatorConfig.tool,
2265
- filepath: ignorePath,
2266
- content: ignoreContent
2267
- });
2763
+ if (generatorConfig.ignoreFileName) {
2764
+ const ignorePath = resolvePath(generatorConfig.ignoreFileName, baseDir);
2765
+ const ignoreContent = generateIgnoreFile2(ignorePatterns.patterns, generatorConfig.tool);
2766
+ outputs.push({
2767
+ tool: generatorConfig.tool,
2768
+ filepath: ignorePath,
2769
+ content: ignoreContent
2770
+ });
2771
+ }
2268
2772
  if (generatorConfig.updateAdditionalConfig) {
2269
2773
  const additionalOutputs = await generatorConfig.updateAdditionalConfig(
2270
2774
  ignorePatterns.patterns,
@@ -2298,7 +2802,7 @@ async function generateAugmentcodeConfig(rules, config, baseDir) {
2298
2802
  "augmentcode",
2299
2803
  config,
2300
2804
  baseDir,
2301
- (0, import_node_path6.join)(".augment", "rules", `${rule.filename}.md`),
2805
+ (0, import_node_path10.join)(".augment", "rules", `${rule.filename}.md`),
2302
2806
  generateRuleFile(rule)
2303
2807
  );
2304
2808
  });
@@ -2351,19 +2855,19 @@ function generateLegacyGuidelinesFile(allRules) {
2351
2855
  }
2352
2856
 
2353
2857
  // src/generators/rules/claudecode.ts
2354
- var import_node_path7 = require("path");
2858
+ var import_node_path11 = require("path");
2355
2859
  async function generateClaudecodeConfig(rules, config, baseDir) {
2356
2860
  const generatorConfig = {
2357
2861
  tool: "claudecode",
2358
2862
  fileExtension: ".md",
2359
- ignoreFileName: ".aiignore",
2863
+ // ignoreFileName omitted - Claude Code uses settings.json permissions.deny instead of ignore files
2360
2864
  generateContent: generateMemoryFile,
2361
2865
  generateRootContent: generateClaudeMarkdown,
2362
2866
  rootFilePath: "CLAUDE.md",
2363
2867
  generateDetailContent: generateMemoryFile,
2364
2868
  detailSubDir: ".claude/memories",
2365
2869
  updateAdditionalConfig: async (ignorePatterns, baseDir2) => {
2366
- const settingsPath = resolvePath((0, import_node_path7.join)(".claude", "settings.json"), baseDir2);
2870
+ const settingsPath = resolvePath((0, import_node_path11.join)(".claude", "settings.json"), baseDir2);
2367
2871
  await updateClaudeSettings(settingsPath, ignorePatterns);
2368
2872
  return [];
2369
2873
  }
@@ -2427,7 +2931,7 @@ async function updateClaudeSettings(settingsPath, ignorePatterns) {
2427
2931
  }
2428
2932
 
2429
2933
  // src/generators/rules/generator-registry.ts
2430
- var import_node_path8 = require("path");
2934
+ var import_node_path12 = require("path");
2431
2935
  function determineCursorRuleType(frontmatter) {
2432
2936
  if (frontmatter.cursorRuleType) {
2433
2937
  return frontmatter.cursorRuleType;
@@ -2507,7 +3011,7 @@ var GENERATOR_REGISTRY = {
2507
3011
  },
2508
3012
  pathResolver: (rule, outputDir) => {
2509
3013
  const baseFilename = rule.filename.replace(/\.md$/, "");
2510
- return (0, import_node_path8.join)(outputDir, `${baseFilename}.instructions.md`);
3014
+ return (0, import_node_path12.join)(outputDir, `${baseFilename}.instructions.md`);
2511
3015
  }
2512
3016
  },
2513
3017
  cursor: {
@@ -2547,7 +3051,7 @@ var GENERATOR_REGISTRY = {
2547
3051
  return lines.join("\n");
2548
3052
  },
2549
3053
  pathResolver: (rule, outputDir) => {
2550
- return (0, import_node_path8.join)(outputDir, `${rule.filename}.mdc`);
3054
+ return (0, import_node_path12.join)(outputDir, `${rule.filename}.mdc`);
2551
3055
  }
2552
3056
  },
2553
3057
  codexcli: {
@@ -2583,10 +3087,10 @@ var GENERATOR_REGISTRY = {
2583
3087
  pathResolver: (rule, outputDir) => {
2584
3088
  const outputFormat = rule.frontmatter.windsurfOutputFormat || "directory";
2585
3089
  if (outputFormat === "single-file") {
2586
- return (0, import_node_path8.join)(outputDir, ".windsurf-rules");
3090
+ return (0, import_node_path12.join)(outputDir, ".windsurf-rules");
2587
3091
  } else {
2588
- const rulesDir = (0, import_node_path8.join)(outputDir, ".windsurf", "rules");
2589
- return (0, import_node_path8.join)(rulesDir, `${rule.filename}.md`);
3092
+ const rulesDir = (0, import_node_path12.join)(outputDir, ".windsurf", "rules");
3093
+ return (0, import_node_path12.join)(rulesDir, `${rule.filename}.md`);
2590
3094
  }
2591
3095
  }
2592
3096
  },
@@ -2850,7 +3354,7 @@ function filterRulesForTool(rules, tool, config) {
2850
3354
  if (!targets.includes(tool)) {
2851
3355
  return false;
2852
3356
  }
2853
- return isToolSpecificRule(rule, tool);
3357
+ return true;
2854
3358
  });
2855
3359
  }
2856
3360
  async function generateForTool(tool, rules, config, baseDir) {
@@ -2905,8 +3409,8 @@ async function generateForTool(tool, rules, config, baseDir) {
2905
3409
  }
2906
3410
 
2907
3411
  // src/core/parser.ts
2908
- var import_node_path9 = require("path");
2909
- var import_gray_matter = __toESM(require("gray-matter"), 1);
3412
+ var import_node_path13 = require("path");
3413
+ var import_gray_matter2 = __toESM(require("gray-matter"), 1);
2910
3414
  async function parseRulesFromDirectory(aiRulesDir) {
2911
3415
  const ignorePatterns = await loadIgnorePatterns();
2912
3416
  const allRuleFiles = await findFiles(aiRulesDir, ".md");
@@ -2940,7 +3444,7 @@ ${errors.join("\n")}`);
2940
3444
  }
2941
3445
  async function parseRuleFile(filepath) {
2942
3446
  const content = await readFileContent(filepath);
2943
- const parsed = (0, import_gray_matter.default)(content);
3447
+ const parsed = (0, import_gray_matter2.default)(content);
2944
3448
  try {
2945
3449
  const validatedData = RuleFrontmatterSchema.parse(parsed.data);
2946
3450
  const frontmatter = {
@@ -2959,7 +3463,7 @@ async function parseRuleFile(filepath) {
2959
3463
  },
2960
3464
  ...validatedData.tags !== void 0 && { tags: validatedData.tags }
2961
3465
  };
2962
- const filename = (0, import_node_path9.basename)(filepath, ".md");
3466
+ const filename = (0, import_node_path13.basename)(filepath, ".md");
2963
3467
  return {
2964
3468
  frontmatter,
2965
3469
  content: parsed.content,
@@ -3067,125 +3571,51 @@ function parseMcpConfig(projectRoot) {
3067
3571
  }
3068
3572
 
3069
3573
  // src/core/mcp-generator.ts
3070
- async function generateMcpConfigs(projectRoot, baseDir, targetTools) {
3071
- const results = [];
3072
- const targetRoot = baseDir || projectRoot;
3073
- const config = parseMcpConfig(projectRoot);
3074
- if (!config) {
3075
- return results;
3076
- }
3077
- const generators = [
3078
- {
3079
- tool: "augmentcode-project",
3080
- path: path4.join(targetRoot, ".mcp.json"),
3081
- generate: () => generateAugmentcodeMcp(config)
3082
- },
3083
- {
3084
- tool: "augmentcode-legacy-project",
3085
- path: path4.join(targetRoot, ".mcp.json"),
3086
- generate: () => generateAugmentcodeMcp(config)
3087
- },
3088
- {
3089
- tool: "claude-project",
3090
- path: path4.join(targetRoot, ".mcp.json"),
3091
- generate: () => generateClaudeMcp(config)
3092
- },
3093
- {
3094
- tool: "copilot-editor",
3095
- path: path4.join(targetRoot, ".vscode", "mcp.json"),
3096
- generate: () => generateCopilotMcp(config, "editor")
3097
- },
3098
- {
3099
- tool: "cursor-project",
3100
- path: path4.join(targetRoot, ".cursor", "mcp.json"),
3101
- generate: () => generateCursorMcp(config)
3102
- },
3103
- {
3104
- tool: "cline-project",
3105
- path: path4.join(targetRoot, ".cline", "mcp.json"),
3106
- generate: () => generateClineMcp(config)
3107
- },
3108
- {
3109
- tool: "codexcli-project",
3110
- path: path4.join(targetRoot, ".codex", "mcp-config.json"),
3111
- generate: () => generateCodexMcp(config)
3112
- },
3113
- {
3114
- tool: "gemini-project",
3115
- path: path4.join(targetRoot, ".gemini", "settings.json"),
3116
- generate: () => generateGeminiCliMcp(config)
3117
- },
3118
- {
3119
- tool: "junie-project",
3120
- path: path4.join(targetRoot, ".junie", "mcp-config.json"),
3121
- generate: () => generateJunieMcp(config)
3122
- },
3123
- {
3124
- tool: "kiro-project",
3125
- path: path4.join(targetRoot, ".kiro", "mcp.json"),
3126
- generate: () => generateKiroMcp(config)
3127
- },
3128
- {
3129
- tool: "roo-project",
3130
- path: path4.join(targetRoot, ".roo", "mcp.json"),
3131
- generate: () => generateRooMcp(config)
3132
- },
3133
- {
3134
- tool: "windsurf-project",
3135
- path: path4.join(targetRoot, "mcp_config.json"),
3136
- generate: () => generateWindsurfMcp(config)
3137
- }
3138
- ];
3139
- const filteredGenerators = targetTools ? generators.filter((g) => {
3140
- const baseTool = g.tool.split("-")[0];
3141
- if (!isToolTarget(baseTool)) {
3142
- return false;
3143
- }
3144
- if (baseTool === "augmentcode") {
3145
- return targetTools.includes("augmentcode") || targetTools.includes("augmentcode-legacy");
3146
- }
3147
- return targetTools.includes(baseTool);
3148
- }) : generators;
3149
- for (const generator of filteredGenerators) {
3150
- try {
3151
- const content = generator.generate();
3152
- const parsed = JSON.parse(content);
3153
- if (generator.tool.includes("augmentcode") || generator.tool.includes("claude") || generator.tool.includes("cline") || generator.tool.includes("codexcli") || generator.tool.includes("cursor") || generator.tool.includes("gemini") || generator.tool.includes("junie") || generator.tool.includes("kiro") || generator.tool.includes("roo") || generator.tool.includes("windsurf")) {
3154
- if (!parsed.mcpServers || Object.keys(parsed.mcpServers).length === 0) {
3155
- results.push({
3156
- tool: generator.tool,
3157
- path: generator.path,
3158
- status: "skipped"
3159
- });
3160
- continue;
3161
- }
3162
- } else if (generator.tool.includes("copilot")) {
3163
- const key = generator.tool.includes("codingAgent") ? "mcpServers" : "servers";
3164
- if (!parsed[key] || Object.keys(parsed[key]).length === 0) {
3165
- results.push({
3166
- tool: generator.tool,
3167
- path: generator.path,
3168
- status: "skipped"
3169
- });
3170
- continue;
3574
+ async function generateMcpConfigurations(mcpConfig, baseDir, targetTools) {
3575
+ const outputs = [];
3576
+ const toolMap = {
3577
+ augmentcode: async (servers, dir) => (await Promise.resolve().then(() => (init_augmentcode(), augmentcode_exports))).generateAugmentcodeMcpConfiguration(
3578
+ servers,
3579
+ dir
3580
+ ),
3581
+ "augmentcode-legacy": async (servers, dir) => (await Promise.resolve().then(() => (init_augmentcode(), augmentcode_exports))).generateAugmentcodeMcpConfiguration(
3582
+ servers,
3583
+ dir
3584
+ ),
3585
+ claudecode: async (servers, dir) => (await Promise.resolve().then(() => (init_claudecode(), claudecode_exports))).generateClaudeMcpConfiguration(
3586
+ servers,
3587
+ dir
3588
+ ),
3589
+ copilot: async (servers, dir) => (await Promise.resolve().then(() => (init_copilot(), copilot_exports))).generateCopilotMcpConfiguration(servers, dir),
3590
+ cursor: async (servers, dir) => (await Promise.resolve().then(() => (init_cursor(), cursor_exports))).generateCursorMcpConfiguration(servers, dir),
3591
+ cline: async (servers, dir) => (await Promise.resolve().then(() => (init_cline(), cline_exports))).generateClineMcpConfiguration(servers, dir),
3592
+ codexcli: async (servers, dir) => (await Promise.resolve().then(() => (init_codexcli(), codexcli_exports))).generateCodexMcpConfiguration(servers, dir),
3593
+ roo: async (servers, dir) => (await Promise.resolve().then(() => (init_roo(), roo_exports))).generateRooMcpConfiguration(servers, dir),
3594
+ geminicli: async (servers, dir) => (await Promise.resolve().then(() => (init_geminicli(), geminicli_exports))).generateGeminiCliMcpConfiguration(
3595
+ servers,
3596
+ dir
3597
+ ),
3598
+ kiro: async (servers, dir) => (await Promise.resolve().then(() => (init_kiro(), kiro_exports))).generateKiroMcpConfiguration(servers, dir),
3599
+ junie: async (servers, dir) => (await Promise.resolve().then(() => (init_junie(), junie_exports))).generateJunieMcpConfiguration(servers, dir),
3600
+ windsurf: async (servers, dir) => (await Promise.resolve().then(() => (init_windsurf(), windsurf_exports))).generateWindsurfMcpConfiguration(
3601
+ servers,
3602
+ dir
3603
+ )
3604
+ };
3605
+ const tools = targetTools || Object.keys(toolMap).filter(isToolTarget);
3606
+ const seenPaths = /* @__PURE__ */ new Set();
3607
+ for (const tool of tools) {
3608
+ if (tool in toolMap) {
3609
+ const results = await toolMap[tool](mcpConfig.mcpServers || {}, baseDir);
3610
+ for (const result of results) {
3611
+ if (!seenPaths.has(result.filepath)) {
3612
+ seenPaths.add(result.filepath);
3613
+ outputs.push({ ...result, tool });
3171
3614
  }
3172
3615
  }
3173
- await writeFileContent(generator.path, content);
3174
- results.push({
3175
- tool: generator.tool,
3176
- path: generator.path,
3177
- status: "success"
3178
- });
3179
- } catch (error) {
3180
- results.push({
3181
- tool: generator.tool,
3182
- path: generator.path,
3183
- status: "error",
3184
- error: error instanceof Error ? error.message : String(error)
3185
- });
3186
3616
  }
3187
3617
  }
3188
- return results;
3618
+ return outputs;
3189
3619
  }
3190
3620
 
3191
3621
  // src/cli/commands/generate.ts
@@ -3262,12 +3692,12 @@ async function generateCommand(options = {}) {
3262
3692
  for (const tool of targetTools) {
3263
3693
  switch (tool) {
3264
3694
  case "augmentcode":
3265
- deleteTasks.push(removeDirectory((0, import_node_path10.join)(".augment", "rules")));
3266
- deleteTasks.push(removeDirectory((0, import_node_path10.join)(".augment", "ignore")));
3695
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".augment", "rules")));
3696
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".augment", "ignore")));
3267
3697
  break;
3268
3698
  case "augmentcode-legacy":
3269
3699
  deleteTasks.push(removeClaudeGeneratedFiles());
3270
- deleteTasks.push(removeDirectory((0, import_node_path10.join)(".augment", "ignore")));
3700
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".augment", "ignore")));
3271
3701
  break;
3272
3702
  case "copilot":
3273
3703
  deleteTasks.push(removeDirectory(config.outputPaths.copilot));
@@ -3280,12 +3710,14 @@ async function generateCommand(options = {}) {
3280
3710
  break;
3281
3711
  case "claudecode":
3282
3712
  deleteTasks.push(removeClaudeGeneratedFiles());
3713
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".claude", "commands")));
3283
3714
  break;
3284
3715
  case "roo":
3285
3716
  deleteTasks.push(removeDirectory(config.outputPaths.roo));
3286
3717
  break;
3287
3718
  case "geminicli":
3288
3719
  deleteTasks.push(removeDirectory(config.outputPaths.geminicli));
3720
+ deleteTasks.push(removeDirectory((0, import_node_path14.join)(".gemini", "commands")));
3289
3721
  break;
3290
3722
  case "kiro":
3291
3723
  deleteTasks.push(removeDirectory(config.outputPaths.kiro));
@@ -3328,33 +3760,69 @@ Generating configurations for base directory: ${baseDir}`);
3328
3760
  }
3329
3761
  let totalMcpOutputs = 0;
3330
3762
  for (const baseDir of baseDirs) {
3331
- const mcpResults = await generateMcpConfigs(
3763
+ try {
3764
+ const mcpConfig = parseMcpConfig(process.cwd());
3765
+ if (!mcpConfig || !mcpConfig.mcpServers || Object.keys(mcpConfig.mcpServers).length === 0) {
3766
+ if (config.verbose) {
3767
+ console.log(`No MCP configuration found for ${baseDir}`);
3768
+ }
3769
+ continue;
3770
+ }
3771
+ const mcpResults = await generateMcpConfigurations(
3772
+ mcpConfig,
3773
+ baseDir === process.cwd() ? "." : baseDir,
3774
+ config.defaultTargets
3775
+ );
3776
+ if (mcpResults.length === 0) {
3777
+ if (config.verbose) {
3778
+ console.log(`No MCP configurations generated for ${baseDir}`);
3779
+ }
3780
+ continue;
3781
+ }
3782
+ for (const result of mcpResults) {
3783
+ await writeFileContent(result.filepath, result.content);
3784
+ console.log(`\u2705 Generated ${result.tool} MCP configuration: ${result.filepath}`);
3785
+ totalMcpOutputs++;
3786
+ }
3787
+ } catch (error) {
3788
+ if (config.verbose) {
3789
+ console.error(
3790
+ `\u274C Failed to generate MCP configurations: ${error instanceof Error ? error.message : String(error)}`
3791
+ );
3792
+ }
3793
+ }
3794
+ }
3795
+ if (config.verbose) {
3796
+ console.log("\nGenerating command files...");
3797
+ }
3798
+ let totalCommandOutputs = 0;
3799
+ for (const baseDir of baseDirs) {
3800
+ const commandResults = await generateCommands(
3332
3801
  process.cwd(),
3333
3802
  baseDir === process.cwd() ? void 0 : baseDir,
3334
3803
  config.defaultTargets
3335
3804
  );
3336
- if (mcpResults.length === 0) {
3805
+ if (commandResults.length === 0) {
3337
3806
  if (config.verbose) {
3338
- console.log(`No MCP configuration found for ${baseDir}`);
3807
+ console.log(`No commands found for ${baseDir}`);
3339
3808
  }
3340
3809
  continue;
3341
3810
  }
3342
- for (const result of mcpResults) {
3343
- if (result.status === "success") {
3344
- console.log(`\u2705 Generated ${result.tool} MCP configuration: ${result.path}`);
3345
- totalMcpOutputs++;
3346
- } else if (result.status === "error") {
3347
- console.error(`\u274C Failed to generate ${result.tool} MCP configuration: ${result.error}`);
3348
- } else if (config.verbose && result.status === "skipped") {
3349
- console.log(`\u23ED\uFE0F Skipped ${result.tool} MCP configuration (no servers configured)`);
3350
- }
3811
+ for (const result of commandResults) {
3812
+ await writeFileContent(result.filepath, result.content);
3813
+ console.log(`\u2705 Generated ${result.tool} command: ${result.filepath}`);
3814
+ totalCommandOutputs++;
3351
3815
  }
3352
3816
  }
3353
- const totalGenerated = totalOutputs + totalMcpOutputs;
3817
+ const totalGenerated = totalOutputs + totalMcpOutputs + totalCommandOutputs;
3354
3818
  if (totalGenerated > 0) {
3819
+ const parts = [];
3820
+ if (totalOutputs > 0) parts.push(`${totalOutputs} configurations`);
3821
+ if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP configurations`);
3822
+ if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
3355
3823
  console.log(
3356
3824
  `
3357
- \u{1F389} All done! Generated ${totalGenerated} file(s) total (${totalOutputs} configurations + ${totalMcpOutputs} MCP configurations)`
3825
+ \u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`
3358
3826
  );
3359
3827
  }
3360
3828
  } catch (error) {
@@ -3365,9 +3833,9 @@ Generating configurations for base directory: ${baseDir}`);
3365
3833
 
3366
3834
  // src/cli/commands/gitignore.ts
3367
3835
  var import_node_fs2 = require("fs");
3368
- var import_node_path11 = require("path");
3836
+ var import_node_path15 = require("path");
3369
3837
  var gitignoreCommand = async () => {
3370
- const gitignorePath = (0, import_node_path11.join)(process.cwd(), ".gitignore");
3838
+ const gitignorePath = (0, import_node_path15.join)(process.cwd(), ".gitignore");
3371
3839
  const rulesFilesToIgnore = [
3372
3840
  "# Generated by rulesync - AI tool configuration files",
3373
3841
  "**/.github/copilot-instructions.md",
@@ -3378,6 +3846,7 @@ var gitignoreCommand = async () => {
3378
3846
  "**/.clineignore",
3379
3847
  "**/CLAUDE.md",
3380
3848
  "**/.claude/memories/",
3849
+ "**/.claude/commands/",
3381
3850
  "**/codex.md",
3382
3851
  "**/.codexignore",
3383
3852
  "**/.roo/rules/",
@@ -3385,6 +3854,7 @@ var gitignoreCommand = async () => {
3385
3854
  "**/.copilotignore",
3386
3855
  "**/GEMINI.md",
3387
3856
  "**/.gemini/memories/",
3857
+ "**/.gemini/commands/",
3388
3858
  "**/.aiexclude",
3389
3859
  "**/.aiignore",
3390
3860
  "**/.augmentignore",
@@ -3431,12 +3901,12 @@ ${linesToAdd.join("\n")}
3431
3901
  };
3432
3902
 
3433
3903
  // src/core/importer.ts
3434
- var import_node_path18 = require("path");
3435
- var import_gray_matter6 = __toESM(require("gray-matter"), 1);
3904
+ var import_node_path22 = require("path");
3905
+ var import_gray_matter7 = __toESM(require("gray-matter"), 1);
3436
3906
 
3437
3907
  // src/parsers/augmentcode.ts
3438
- var import_node_path12 = require("path");
3439
- var import_gray_matter2 = __toESM(require("gray-matter"), 1);
3908
+ var import_node_path16 = require("path");
3909
+ var import_gray_matter3 = __toESM(require("gray-matter"), 1);
3440
3910
 
3441
3911
  // src/utils/parser-helpers.ts
3442
3912
  function createParseResult() {
@@ -3484,7 +3954,7 @@ async function parseAugmentcodeLegacyConfiguration(baseDir = process.cwd()) {
3484
3954
  async function parseUnifiedAugmentcode(baseDir, config) {
3485
3955
  const result = createParseResult();
3486
3956
  if (config.rulesDir) {
3487
- const rulesDir = (0, import_node_path12.join)(baseDir, config.rulesDir);
3957
+ const rulesDir = (0, import_node_path16.join)(baseDir, config.rulesDir);
3488
3958
  if (await fileExists(rulesDir)) {
3489
3959
  const rulesResult = await parseAugmentRules(rulesDir, config);
3490
3960
  addRules(result, rulesResult.rules);
@@ -3497,7 +3967,7 @@ async function parseUnifiedAugmentcode(baseDir, config) {
3497
3967
  }
3498
3968
  }
3499
3969
  if (config.legacyFilePath) {
3500
- const legacyPath = (0, import_node_path12.join)(baseDir, config.legacyFilePath);
3970
+ const legacyPath = (0, import_node_path16.join)(baseDir, config.legacyFilePath);
3501
3971
  if (await fileExists(legacyPath)) {
3502
3972
  const legacyResult = await parseAugmentGuidelines(legacyPath, config);
3503
3973
  if (legacyResult.rule) {
@@ -3521,16 +3991,16 @@ async function parseAugmentRules(rulesDir, config) {
3521
3991
  const files = await readdir2(rulesDir);
3522
3992
  for (const file of files) {
3523
3993
  if (file.endsWith(".md") || file.endsWith(".mdc")) {
3524
- const filePath = (0, import_node_path12.join)(rulesDir, file);
3994
+ const filePath = (0, import_node_path16.join)(rulesDir, file);
3525
3995
  try {
3526
3996
  const rawContent = await readFileContent(filePath);
3527
- const parsed = (0, import_gray_matter2.default)(rawContent);
3997
+ const parsed = (0, import_gray_matter3.default)(rawContent);
3528
3998
  const frontmatterData = parsed.data;
3529
3999
  const ruleType = frontmatterData.type || "manual";
3530
4000
  const description = frontmatterData.description || "";
3531
4001
  const tags = Array.isArray(frontmatterData.tags) ? frontmatterData.tags : void 0;
3532
4002
  const isRoot = ruleType === "always";
3533
- const filename = (0, import_node_path12.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
4003
+ const filename = (0, import_node_path16.basename)(file, file.endsWith(".mdc") ? ".mdc" : ".md");
3534
4004
  const frontmatter = {
3535
4005
  root: isRoot,
3536
4006
  targets: [config.targetName],
@@ -3588,8 +4058,8 @@ async function parseAugmentGuidelines(guidelinesPath, config) {
3588
4058
  }
3589
4059
 
3590
4060
  // src/parsers/shared-helpers.ts
3591
- var import_node_path13 = require("path");
3592
- var import_gray_matter3 = __toESM(require("gray-matter"), 1);
4061
+ var import_node_path17 = require("path");
4062
+ var import_gray_matter4 = __toESM(require("gray-matter"), 1);
3593
4063
  async function parseConfigurationFiles(baseDir = process.cwd(), config) {
3594
4064
  const errors = [];
3595
4065
  const rules = [];
@@ -3602,7 +4072,7 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
3602
4072
  let content;
3603
4073
  let frontmatter;
3604
4074
  if (mainFile.useFrontmatter) {
3605
- const parsed = (0, import_gray_matter3.default)(rawContent);
4075
+ const parsed = (0, import_gray_matter4.default)(rawContent);
3606
4076
  content = parsed.content.trim();
3607
4077
  const parsedFrontmatter = parsed.data;
3608
4078
  frontmatter = {
@@ -3644,14 +4114,14 @@ async function parseConfigurationFiles(baseDir = process.cwd(), config) {
3644
4114
  const files = await readdir2(dirPath);
3645
4115
  for (const file of files) {
3646
4116
  if (file.endsWith(dirConfig.filePattern)) {
3647
- const filePath = (0, import_node_path13.join)(dirPath, file);
4117
+ const filePath = (0, import_node_path17.join)(dirPath, file);
3648
4118
  const fileResult = await safeAsyncOperation(async () => {
3649
4119
  const rawContent = await readFileContent(filePath);
3650
4120
  let content;
3651
4121
  let frontmatter;
3652
4122
  const filename = file.replace(new RegExp(`\\${dirConfig.filePattern}$`), "");
3653
4123
  if (dirConfig.filePattern === ".instructions.md") {
3654
- const parsed = (0, import_gray_matter3.default)(rawContent);
4124
+ const parsed = (0, import_gray_matter4.default)(rawContent);
3655
4125
  content = parsed.content.trim();
3656
4126
  const parsedFrontmatter = parsed.data;
3657
4127
  frontmatter = {
@@ -3717,6 +4187,13 @@ async function parseMemoryBasedConfiguration(baseDir = process.cwd(), config) {
3717
4187
  const memoryRules = await parseMemoryFiles(memoryDir, config);
3718
4188
  rules.push(...memoryRules);
3719
4189
  }
4190
+ if (config.commandsDirPath) {
4191
+ const commandsDir = resolvePath(config.commandsDirPath, baseDir);
4192
+ if (await fileExists(commandsDir)) {
4193
+ const commandsRules = await parseCommandsFiles(commandsDir, config);
4194
+ rules.push(...commandsRules);
4195
+ }
4196
+ }
3720
4197
  const settingsPath = resolvePath(config.settingsPath, baseDir);
3721
4198
  if (await fileExists(settingsPath)) {
3722
4199
  const settingsResult = await parseSettingsFile(settingsPath, config.tool);
@@ -3782,10 +4259,10 @@ async function parseMemoryFiles(memoryDir, config) {
3782
4259
  const files = await readdir2(memoryDir);
3783
4260
  for (const file of files) {
3784
4261
  if (file.endsWith(".md")) {
3785
- const filePath = (0, import_node_path13.join)(memoryDir, file);
4262
+ const filePath = (0, import_node_path17.join)(memoryDir, file);
3786
4263
  const content = await readFileContent(filePath);
3787
4264
  if (content.trim()) {
3788
- const filename = (0, import_node_path13.basename)(file, ".md");
4265
+ const filename = (0, import_node_path17.basename)(file, ".md");
3789
4266
  const frontmatter = {
3790
4267
  root: false,
3791
4268
  targets: [config.tool],
@@ -3805,6 +4282,54 @@ async function parseMemoryFiles(memoryDir, config) {
3805
4282
  }
3806
4283
  return rules;
3807
4284
  }
4285
+ async function parseCommandsFiles(commandsDir, config) {
4286
+ const rules = [];
4287
+ try {
4288
+ const { readdir: readdir2 } = await import("fs/promises");
4289
+ const files = await readdir2(commandsDir);
4290
+ for (const file of files) {
4291
+ if (file.endsWith(".md")) {
4292
+ const filePath = (0, import_node_path17.join)(commandsDir, file);
4293
+ const content = await readFileContent(filePath);
4294
+ if (content.trim()) {
4295
+ const filename = (0, import_node_path17.basename)(file, ".md");
4296
+ let frontmatter;
4297
+ let ruleContent;
4298
+ try {
4299
+ const parsed = (0, import_gray_matter4.default)(content);
4300
+ ruleContent = parsed.content.trim();
4301
+ const parsedFrontmatter = parsed.data;
4302
+ frontmatter = {
4303
+ root: false,
4304
+ targets: [config.tool],
4305
+ description: parsedFrontmatter.description || `Command: ${filename}`,
4306
+ globs: ["**/*"]
4307
+ };
4308
+ } catch {
4309
+ ruleContent = content.trim();
4310
+ frontmatter = {
4311
+ root: false,
4312
+ targets: [config.tool],
4313
+ description: `Command: ${filename}`,
4314
+ globs: ["**/*"]
4315
+ };
4316
+ }
4317
+ if (ruleContent) {
4318
+ rules.push({
4319
+ frontmatter,
4320
+ content: ruleContent,
4321
+ filename,
4322
+ filepath: filePath,
4323
+ type: "command"
4324
+ });
4325
+ }
4326
+ }
4327
+ }
4328
+ }
4329
+ } catch {
4330
+ }
4331
+ return rules;
4332
+ }
3808
4333
  async function parseSettingsFile(settingsPath, tool) {
3809
4334
  const errors = [];
3810
4335
  let ignorePatterns;
@@ -3852,7 +4377,8 @@ async function parseClaudeConfiguration(baseDir = process.cwd()) {
3852
4377
  settingsPath: ".claude/settings.json",
3853
4378
  mainDescription: "Main Claude Code configuration",
3854
4379
  memoryDescription: "Memory file",
3855
- filenamePrefix: "claude"
4380
+ filenamePrefix: "claude",
4381
+ commandsDirPath: ".claude/commands"
3856
4382
  });
3857
4383
  }
3858
4384
 
@@ -3877,7 +4403,7 @@ async function parseClineConfiguration(baseDir = process.cwd()) {
3877
4403
  }
3878
4404
 
3879
4405
  // src/parsers/codexcli.ts
3880
- var import_node_path14 = require("path");
4406
+ var import_node_path18 = require("path");
3881
4407
 
3882
4408
  // src/parsers/copilot.ts
3883
4409
  async function parseCopilotConfiguration(baseDir = process.cwd()) {
@@ -3900,10 +4426,10 @@ async function parseCopilotConfiguration(baseDir = process.cwd()) {
3900
4426
  }
3901
4427
 
3902
4428
  // src/parsers/cursor.ts
3903
- var import_node_path15 = require("path");
3904
- var import_gray_matter4 = __toESM(require("gray-matter"), 1);
4429
+ var import_node_path19 = require("path");
4430
+ var import_gray_matter5 = __toESM(require("gray-matter"), 1);
3905
4431
  var import_js_yaml = require("js-yaml");
3906
- var import_mini7 = require("zod/mini");
4432
+ var import_mini8 = require("zod/mini");
3907
4433
  var customMatterOptions = {
3908
4434
  engines: {
3909
4435
  yaml: {
@@ -3931,7 +4457,7 @@ var customMatterOptions = {
3931
4457
  }
3932
4458
  };
3933
4459
  function convertCursorMdcFrontmatter(cursorFrontmatter, _filename) {
3934
- const FrontmatterSchema = import_mini7.z.record(import_mini7.z.string(), import_mini7.z.unknown());
4460
+ const FrontmatterSchema = import_mini8.z.record(import_mini8.z.string(), import_mini8.z.unknown());
3935
4461
  const parseResult = FrontmatterSchema.safeParse(cursorFrontmatter);
3936
4462
  if (!parseResult.success) {
3937
4463
  return {
@@ -4025,11 +4551,11 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
4025
4551
  const rules = [];
4026
4552
  let ignorePatterns;
4027
4553
  let mcpServers;
4028
- const cursorFilePath = (0, import_node_path15.join)(baseDir, ".cursorrules");
4554
+ const cursorFilePath = (0, import_node_path19.join)(baseDir, ".cursorrules");
4029
4555
  if (await fileExists(cursorFilePath)) {
4030
4556
  try {
4031
4557
  const rawContent = await readFileContent(cursorFilePath);
4032
- const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
4558
+ const parsed = (0, import_gray_matter5.default)(rawContent, customMatterOptions);
4033
4559
  const content = parsed.content.trim();
4034
4560
  if (content) {
4035
4561
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, "cursorrules");
@@ -4046,20 +4572,20 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
4046
4572
  errors.push(`Failed to parse .cursorrules file: ${errorMessage}`);
4047
4573
  }
4048
4574
  }
4049
- const cursorRulesDir = (0, import_node_path15.join)(baseDir, ".cursor", "rules");
4575
+ const cursorRulesDir = (0, import_node_path19.join)(baseDir, ".cursor", "rules");
4050
4576
  if (await fileExists(cursorRulesDir)) {
4051
4577
  try {
4052
4578
  const { readdir: readdir2 } = await import("fs/promises");
4053
4579
  const files = await readdir2(cursorRulesDir);
4054
4580
  for (const file of files) {
4055
4581
  if (file.endsWith(".mdc")) {
4056
- const filePath = (0, import_node_path15.join)(cursorRulesDir, file);
4582
+ const filePath = (0, import_node_path19.join)(cursorRulesDir, file);
4057
4583
  try {
4058
4584
  const rawContent = await readFileContent(filePath);
4059
- const parsed = (0, import_gray_matter4.default)(rawContent, customMatterOptions);
4585
+ const parsed = (0, import_gray_matter5.default)(rawContent, customMatterOptions);
4060
4586
  const content = parsed.content.trim();
4061
4587
  if (content) {
4062
- const filename = (0, import_node_path15.basename)(file, ".mdc");
4588
+ const filename = (0, import_node_path19.basename)(file, ".mdc");
4063
4589
  const frontmatter = convertCursorMdcFrontmatter(parsed.data, filename);
4064
4590
  rules.push({
4065
4591
  frontmatter,
@@ -4082,7 +4608,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
4082
4608
  if (rules.length === 0) {
4083
4609
  errors.push("No Cursor configuration files found (.cursorrules or .cursor/rules/*.mdc)");
4084
4610
  }
4085
- const cursorIgnorePath = (0, import_node_path15.join)(baseDir, ".cursorignore");
4611
+ const cursorIgnorePath = (0, import_node_path19.join)(baseDir, ".cursorignore");
4086
4612
  if (await fileExists(cursorIgnorePath)) {
4087
4613
  try {
4088
4614
  const content = await readFileContent(cursorIgnorePath);
@@ -4095,7 +4621,7 @@ async function parseCursorConfiguration(baseDir = process.cwd()) {
4095
4621
  errors.push(`Failed to parse .cursorignore: ${errorMessage}`);
4096
4622
  }
4097
4623
  }
4098
- const cursorMcpPath = (0, import_node_path15.join)(baseDir, ".cursor", "mcp.json");
4624
+ const cursorMcpPath = (0, import_node_path19.join)(baseDir, ".cursor", "mcp.json");
4099
4625
  if (await fileExists(cursorMcpPath)) {
4100
4626
  try {
4101
4627
  const content = await readFileContent(cursorMcpPath);
@@ -4139,16 +4665,17 @@ async function parseGeminiConfiguration(baseDir = process.cwd()) {
4139
4665
  additionalIgnoreFile: {
4140
4666
  path: ".aiexclude",
4141
4667
  parser: parseAiexclude
4142
- }
4668
+ },
4669
+ commandsDirPath: ".gemini/commands"
4143
4670
  });
4144
4671
  }
4145
4672
 
4146
4673
  // src/parsers/junie.ts
4147
- var import_node_path16 = require("path");
4674
+ var import_node_path20 = require("path");
4148
4675
  async function parseJunieConfiguration(baseDir = process.cwd()) {
4149
4676
  const errors = [];
4150
4677
  const rules = [];
4151
- const guidelinesPath = (0, import_node_path16.join)(baseDir, ".junie", "guidelines.md");
4678
+ const guidelinesPath = (0, import_node_path20.join)(baseDir, ".junie", "guidelines.md");
4152
4679
  if (!await fileExists(guidelinesPath)) {
4153
4680
  errors.push(".junie/guidelines.md file not found");
4154
4681
  return { rules, errors };
@@ -4201,8 +4728,8 @@ async function parseRooConfiguration(baseDir = process.cwd()) {
4201
4728
 
4202
4729
  // src/parsers/windsurf.ts
4203
4730
  var import_promises3 = require("fs/promises");
4204
- var import_node_path17 = require("path");
4205
- var import_gray_matter5 = __toESM(require("gray-matter"), 1);
4731
+ var import_node_path21 = require("path");
4732
+ var import_gray_matter6 = __toESM(require("gray-matter"), 1);
4206
4733
 
4207
4734
  // src/core/importer.ts
4208
4735
  async function importConfiguration(options) {
@@ -4288,7 +4815,7 @@ async function importConfiguration(options) {
4288
4815
  if (rules.length === 0 && !ignorePatterns && !mcpServers) {
4289
4816
  return { success: false, rulesCreated: 0, errors };
4290
4817
  }
4291
- const rulesDirPath = (0, import_node_path18.join)(baseDir, rulesDir);
4818
+ const rulesDirPath = (0, import_node_path22.join)(baseDir, rulesDir);
4292
4819
  try {
4293
4820
  const { mkdir: mkdir3 } = await import("fs/promises");
4294
4821
  await mkdir3(rulesDirPath, { recursive: true });
@@ -4301,8 +4828,13 @@ async function importConfiguration(options) {
4301
4828
  for (const rule of rules) {
4302
4829
  try {
4303
4830
  const baseFilename = rule.filename;
4304
- const filename = await generateUniqueFilename(rulesDirPath, baseFilename);
4305
- const filePath = (0, import_node_path18.join)(rulesDirPath, `${filename}.md`);
4831
+ let targetDir = rulesDirPath;
4832
+ if (rule.type === "command") {
4833
+ targetDir = (0, import_node_path22.join)(rulesDirPath, "commands");
4834
+ const { mkdir: mkdir3 } = await import("fs/promises");
4835
+ await mkdir3(targetDir, { recursive: true });
4836
+ }
4837
+ const filePath = (0, import_node_path22.join)(targetDir, `${baseFilename}.md`);
4306
4838
  const content = generateRuleFileContent(rule);
4307
4839
  await writeFileContent(filePath, content);
4308
4840
  rulesCreated++;
@@ -4317,7 +4849,7 @@ async function importConfiguration(options) {
4317
4849
  let ignoreFileCreated = false;
4318
4850
  if (ignorePatterns && ignorePatterns.length > 0) {
4319
4851
  try {
4320
- const rulesyncignorePath = (0, import_node_path18.join)(baseDir, ".rulesyncignore");
4852
+ const rulesyncignorePath = (0, import_node_path22.join)(baseDir, ".rulesyncignore");
4321
4853
  const ignoreContent = `${ignorePatterns.join("\n")}
4322
4854
  `;
4323
4855
  await writeFileContent(rulesyncignorePath, ignoreContent);
@@ -4333,7 +4865,7 @@ async function importConfiguration(options) {
4333
4865
  let mcpFileCreated = false;
4334
4866
  if (mcpServers && Object.keys(mcpServers).length > 0) {
4335
4867
  try {
4336
- const mcpPath = (0, import_node_path18.join)(baseDir, rulesDir, ".mcp.json");
4868
+ const mcpPath = (0, import_node_path22.join)(baseDir, rulesDir, ".mcp.json");
4337
4869
  const mcpContent = `${JSON.stringify({ mcpServers }, null, 2)}
4338
4870
  `;
4339
4871
  await writeFileContent(mcpPath, mcpContent);
@@ -4355,17 +4887,16 @@ async function importConfiguration(options) {
4355
4887
  };
4356
4888
  }
4357
4889
  function generateRuleFileContent(rule) {
4358
- const frontmatter = import_gray_matter6.default.stringify("", rule.frontmatter);
4359
- return frontmatter + rule.content;
4360
- }
4361
- async function generateUniqueFilename(rulesDir, baseFilename) {
4362
- let filename = baseFilename;
4363
- let counter = 1;
4364
- while (await fileExists((0, import_node_path18.join)(rulesDir, `${filename}.md`))) {
4365
- filename = `${baseFilename}-${counter}`;
4366
- counter++;
4890
+ if (rule.type === "command") {
4891
+ const simplifiedFrontmatter = {
4892
+ description: rule.frontmatter.description,
4893
+ targets: rule.frontmatter.targets
4894
+ };
4895
+ const frontmatter2 = import_gray_matter7.default.stringify("", simplifiedFrontmatter);
4896
+ return frontmatter2 + rule.content;
4367
4897
  }
4368
- return filename;
4898
+ const frontmatter = import_gray_matter7.default.stringify("", rule.frontmatter);
4899
+ return frontmatter + rule.content;
4369
4900
  }
4370
4901
 
4371
4902
  // src/cli/commands/import.ts
@@ -4428,7 +4959,7 @@ async function importCommand(options = {}) {
4428
4959
  }
4429
4960
 
4430
4961
  // src/cli/commands/init.ts
4431
- var import_node_path19 = require("path");
4962
+ var import_node_path23 = require("path");
4432
4963
  async function initCommand() {
4433
4964
  const aiRulesDir = ".rulesync";
4434
4965
  console.log("Initializing rulesync...");
@@ -4475,7 +5006,7 @@ globs: ["**/*"]
4475
5006
  - Follow single responsibility principle
4476
5007
  `
4477
5008
  };
4478
- const filepath = (0, import_node_path19.join)(aiRulesDir, sampleFile.filename);
5009
+ const filepath = (0, import_node_path23.join)(aiRulesDir, sampleFile.filename);
4479
5010
  if (!await fileExists(filepath)) {
4480
5011
  await writeFileContent(filepath, sampleFile.content);
4481
5012
  console.log(`Created ${filepath}`);
@@ -4619,7 +5150,7 @@ async function watchCommand() {
4619
5150
 
4620
5151
  // src/cli/index.ts
4621
5152
  var program = new import_commander.Command();
4622
- program.name("rulesync").description("Unified AI rules management CLI tool").version("0.57.0");
5153
+ program.name("rulesync").description("Unified AI rules management CLI tool").version("0.59.0");
4623
5154
  program.command("init").description("Initialize rulesync in current directory").action(initCommand);
4624
5155
  program.command("add <filename>").description("Add a new rule file").action(addCommand);
4625
5156
  program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);