rulesync 8.9.0 → 8.11.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/cli/index.js CHANGED
@@ -53,8 +53,10 @@ import {
53
53
  SKILL_FILE_NAME,
54
54
  SkillsProcessor,
55
55
  SubagentsProcessor,
56
+ ToolTargetSchema,
56
57
  checkPathTraversal,
57
58
  checkRulesyncDirExists,
59
+ convertFromTool,
58
60
  createTempDirectory,
59
61
  directoryExists,
60
62
  ensureDir,
@@ -77,7 +79,7 @@ import {
77
79
  stringifyFrontmatter,
78
80
  toPosixPath,
79
81
  writeFileContent
80
- } from "../chunk-EHXIVMY2.js";
82
+ } from "../chunk-ZX2YPC22.js";
81
83
 
82
84
  // src/cli/index.ts
83
85
  import { Command } from "commander";
@@ -85,6 +87,81 @@ import { Command } from "commander";
85
87
  // src/utils/parse-comma-separated-list.ts
86
88
  var parseCommaSeparatedList = (value) => value.split(",").map((s) => s.trim()).filter(Boolean);
87
89
 
90
+ // src/utils/result.ts
91
+ function calculateTotalCount(result) {
92
+ return result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount + result.hooksCount + result.permissionsCount;
93
+ }
94
+
95
+ // src/cli/commands/convert.ts
96
+ function parseToolTarget(value, label) {
97
+ const result = ToolTargetSchema.safeParse(value);
98
+ if (!result.success) {
99
+ throw new CLIError(
100
+ `Invalid ${label} tool '${value}'. Must be one of: ${ALL_TOOL_TARGETS.join(", ")}`,
101
+ ErrorCodes.CONVERT_FAILED
102
+ );
103
+ }
104
+ return result.data;
105
+ }
106
+ async function convertCommand(logger5, options) {
107
+ const fromTool = parseToolTarget(options.from ?? "", "source");
108
+ const toToolsRaw = (options.to ?? []).map((t) => parseToolTarget(t, "destination"));
109
+ const toTools = Array.from(new Set(toToolsRaw));
110
+ if (toTools.includes(fromTool)) {
111
+ throw new CLIError(
112
+ `Destination tools must not include the source tool '${fromTool}'. Converting a tool onto itself is likely a mistake and may cause lossy round-trips.`,
113
+ ErrorCodes.CONVERT_FAILED
114
+ );
115
+ }
116
+ const config = await ConfigResolver.resolve({
117
+ ...options,
118
+ targets: [fromTool, ...toTools],
119
+ features: options.features ?? ["*"]
120
+ });
121
+ const isPreview = config.isPreviewMode();
122
+ const modePrefix = isPreview ? "[DRY RUN] " : "";
123
+ logger5.debug(`Converting files from ${fromTool} to ${toTools.join(", ")}...`);
124
+ const result = await convertFromTool({ config, fromTool, toTools, logger: logger5 });
125
+ const totalConverted = calculateTotalCount(result);
126
+ if (totalConverted === 0) {
127
+ const enabledFeatures = config.getFeatures(fromTool).join(", ");
128
+ logger5.warn(`No files converted for enabled features: ${enabledFeatures}`);
129
+ return;
130
+ }
131
+ if (logger5.jsonMode) {
132
+ logger5.captureData("from", fromTool);
133
+ logger5.captureData("to", toTools);
134
+ logger5.captureData("dryRun", isPreview);
135
+ logger5.captureData("features", {
136
+ rules: { count: result.rulesCount },
137
+ ignore: { count: result.ignoreCount },
138
+ mcp: { count: result.mcpCount },
139
+ commands: { count: result.commandsCount },
140
+ subagents: { count: result.subagentsCount },
141
+ skills: { count: result.skillsCount },
142
+ hooks: { count: result.hooksCount },
143
+ permissions: { count: result.permissionsCount }
144
+ });
145
+ logger5.captureData("totalFiles", totalConverted);
146
+ }
147
+ const parts = [];
148
+ if (result.rulesCount > 0) parts.push(`${result.rulesCount} rules`);
149
+ if (result.ignoreCount > 0) parts.push(`${result.ignoreCount} ignore files`);
150
+ if (result.mcpCount > 0) parts.push(`${result.mcpCount} MCP files`);
151
+ if (result.commandsCount > 0) parts.push(`${result.commandsCount} commands`);
152
+ if (result.subagentsCount > 0) parts.push(`${result.subagentsCount} subagents`);
153
+ if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
154
+ if (result.hooksCount > 0) parts.push(`${result.hooksCount} hooks`);
155
+ if (result.permissionsCount > 0) parts.push(`${result.permissionsCount} permissions`);
156
+ const verbPhrase = isPreview ? "Would convert" : "Converted";
157
+ const summary = `${modePrefix}${verbPhrase} ${totalConverted} file(s) total from ${fromTool} to ${toTools.join(", ")} (${parts.join(" + ")})`;
158
+ if (isPreview) {
159
+ logger5.info(summary);
160
+ } else {
161
+ logger5.success(summary);
162
+ }
163
+ }
164
+
88
165
  // src/lib/fetch.ts
89
166
  import { join, posix } from "path";
90
167
  import { Semaphore } from "es-toolkit/promise";
@@ -1032,11 +1109,6 @@ async function fetchCommand(logger5, options) {
1032
1109
  }
1033
1110
  }
1034
1111
 
1035
- // src/utils/result.ts
1036
- function calculateTotalCount(result) {
1037
- return result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount + result.hooksCount + result.permissionsCount;
1038
- }
1039
-
1040
1112
  // src/cli/commands/generate.ts
1041
1113
  function logFeatureResult(logger5, params) {
1042
1114
  const { count, paths, featureName, isPreview, modePrefix } = params;
@@ -4110,7 +4182,7 @@ async function runGhInstall(logger5, options) {
4110
4182
  import { FastMCP } from "fastmcp";
4111
4183
 
4112
4184
  // src/mcp/tools.ts
4113
- import { z as z18 } from "zod/mini";
4185
+ import { z as z19 } from "zod/mini";
4114
4186
 
4115
4187
  // src/mcp/commands.ts
4116
4188
  import { basename as basename2, join as join13 } from "path";
@@ -4299,16 +4371,118 @@ var commandTools = {
4299
4371
  }
4300
4372
  };
4301
4373
 
4302
- // src/mcp/generate.ts
4374
+ // src/mcp/convert.ts
4303
4375
  import { z as z9 } from "zod/mini";
4304
- var generateOptionsSchema = z9.object({
4305
- targets: z9.optional(z9.array(z9.string())),
4376
+ var convertOptionsSchema = z9.object({
4377
+ from: z9.string(),
4378
+ to: z9.array(z9.string()),
4306
4379
  features: z9.optional(z9.array(z9.string())),
4307
- delete: z9.optional(z9.boolean()),
4308
4380
  global: z9.optional(z9.boolean()),
4309
- simulateCommands: z9.optional(z9.boolean()),
4310
- simulateSubagents: z9.optional(z9.boolean()),
4311
- simulateSkills: z9.optional(z9.boolean())
4381
+ dryRun: z9.optional(z9.boolean())
4382
+ });
4383
+ function parseToolTarget2(value, label) {
4384
+ const result = ToolTargetSchema.safeParse(value);
4385
+ if (!result.success) {
4386
+ throw new Error(
4387
+ `Invalid ${label} tool '${value}'. Must be one of: ${ALL_TOOL_TARGETS.join(", ")}`
4388
+ );
4389
+ }
4390
+ return result.data;
4391
+ }
4392
+ async function executeConvert(options) {
4393
+ try {
4394
+ if (!options.from) {
4395
+ return {
4396
+ success: false,
4397
+ error: "from is required. Please specify a source tool to convert from."
4398
+ };
4399
+ }
4400
+ if (!options.to || options.to.length === 0) {
4401
+ return {
4402
+ success: false,
4403
+ error: "to is required and must not be empty. Please specify destination tools."
4404
+ };
4405
+ }
4406
+ const fromTool = parseToolTarget2(options.from, "source");
4407
+ const toToolsRaw = options.to.map((t) => parseToolTarget2(t, "destination"));
4408
+ const toTools = Array.from(new Set(toToolsRaw));
4409
+ if (toTools.includes(fromTool)) {
4410
+ return {
4411
+ success: false,
4412
+ error: `Destination tools must not include the source tool '${fromTool}'. Converting a tool onto itself is likely a mistake and may cause lossy round-trips.`
4413
+ };
4414
+ }
4415
+ const config = await ConfigResolver.resolve({
4416
+ targets: [fromTool, ...toTools],
4417
+ // eslint-disable-next-line no-type-assertion/no-type-assertion
4418
+ features: options.features ?? ["*"],
4419
+ global: options.global,
4420
+ dryRun: options.dryRun,
4421
+ // Always use default baseDirs (process.cwd()) and configPath
4422
+ // verbose and silent are meaningless in MCP context
4423
+ verbose: false,
4424
+ silent: true
4425
+ });
4426
+ const logger5 = new ConsoleLogger({ verbose: false, silent: true });
4427
+ const convertResult = await convertFromTool({ config, fromTool, toTools, logger: logger5 });
4428
+ return buildSuccessResponse({ convertResult, config, fromTool, toTools });
4429
+ } catch (error) {
4430
+ return {
4431
+ success: false,
4432
+ error: formatError(error)
4433
+ };
4434
+ }
4435
+ }
4436
+ function buildSuccessResponse(params) {
4437
+ const { convertResult, config, fromTool, toTools } = params;
4438
+ const totalCount = calculateTotalCount(convertResult);
4439
+ return {
4440
+ success: true,
4441
+ result: {
4442
+ rulesCount: convertResult.rulesCount,
4443
+ ignoreCount: convertResult.ignoreCount,
4444
+ mcpCount: convertResult.mcpCount,
4445
+ commandsCount: convertResult.commandsCount,
4446
+ subagentsCount: convertResult.subagentsCount,
4447
+ skillsCount: convertResult.skillsCount,
4448
+ hooksCount: convertResult.hooksCount,
4449
+ permissionsCount: convertResult.permissionsCount,
4450
+ totalCount
4451
+ },
4452
+ config: {
4453
+ from: fromTool,
4454
+ to: toTools,
4455
+ features: config.getFeatures(),
4456
+ global: config.getGlobal(),
4457
+ dryRun: config.isPreviewMode()
4458
+ }
4459
+ };
4460
+ }
4461
+ var convertToolSchemas = {
4462
+ executeConvert: convertOptionsSchema
4463
+ };
4464
+ var convertTools = {
4465
+ executeConvert: {
4466
+ name: "executeConvert",
4467
+ description: "Execute the rulesync convert command to convert configuration files between AI tools without writing intermediate .rulesync/ files. Requires a source tool (from) and one or more destination tools (to).",
4468
+ parameters: convertToolSchemas.executeConvert,
4469
+ execute: async (options) => {
4470
+ const result = await executeConvert(options);
4471
+ return JSON.stringify(result, null, 2);
4472
+ }
4473
+ }
4474
+ };
4475
+
4476
+ // src/mcp/generate.ts
4477
+ import { z as z10 } from "zod/mini";
4478
+ var generateOptionsSchema = z10.object({
4479
+ targets: z10.optional(z10.array(z10.string())),
4480
+ features: z10.optional(z10.array(z10.string())),
4481
+ delete: z10.optional(z10.boolean()),
4482
+ global: z10.optional(z10.boolean()),
4483
+ simulateCommands: z10.optional(z10.boolean()),
4484
+ simulateSubagents: z10.optional(z10.boolean()),
4485
+ simulateSkills: z10.optional(z10.boolean())
4312
4486
  });
4313
4487
  async function executeGenerate(options = {}) {
4314
4488
  try {
@@ -4336,7 +4510,7 @@ async function executeGenerate(options = {}) {
4336
4510
  });
4337
4511
  const logger5 = new ConsoleLogger({ verbose: false, silent: true });
4338
4512
  const generateResult = await generate({ config, logger: logger5 });
4339
- return buildSuccessResponse({ generateResult, config });
4513
+ return buildSuccessResponse2({ generateResult, config });
4340
4514
  } catch (error) {
4341
4515
  return {
4342
4516
  success: false,
@@ -4344,7 +4518,7 @@ async function executeGenerate(options = {}) {
4344
4518
  };
4345
4519
  }
4346
4520
  }
4347
- function buildSuccessResponse(params) {
4521
+ function buildSuccessResponse2(params) {
4348
4522
  const { generateResult, config } = params;
4349
4523
  const totalCount = calculateTotalCount(generateResult);
4350
4524
  return {
@@ -4388,7 +4562,7 @@ var generateTools = {
4388
4562
 
4389
4563
  // src/mcp/hooks.ts
4390
4564
  import { join as join14 } from "path";
4391
- import { z as z10 } from "zod/mini";
4565
+ import { z as z11 } from "zod/mini";
4392
4566
  var maxHooksSizeBytes = 1024 * 1024;
4393
4567
  async function getHooksFile() {
4394
4568
  try {
@@ -4477,11 +4651,11 @@ async function deleteHooksFile() {
4477
4651
  }
4478
4652
  }
4479
4653
  var hooksToolSchemas = {
4480
- getHooksFile: z10.object({}),
4481
- putHooksFile: z10.object({
4482
- content: z10.string()
4654
+ getHooksFile: z11.object({}),
4655
+ putHooksFile: z11.object({
4656
+ content: z11.string()
4483
4657
  }),
4484
- deleteHooksFile: z10.object({})
4658
+ deleteHooksFile: z11.object({})
4485
4659
  };
4486
4660
  var hooksTools = {
4487
4661
  getHooksFile: {
@@ -4515,7 +4689,7 @@ var hooksTools = {
4515
4689
 
4516
4690
  // src/mcp/ignore.ts
4517
4691
  import { join as join15 } from "path";
4518
- import { z as z11 } from "zod/mini";
4692
+ import { z as z12 } from "zod/mini";
4519
4693
  var maxIgnoreFileSizeBytes = 100 * 1024;
4520
4694
  async function getIgnoreFile() {
4521
4695
  const ignoreFilePath = join15(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
@@ -4578,11 +4752,11 @@ async function deleteIgnoreFile() {
4578
4752
  }
4579
4753
  }
4580
4754
  var ignoreToolSchemas = {
4581
- getIgnoreFile: z11.object({}),
4582
- putIgnoreFile: z11.object({
4583
- content: z11.string()
4755
+ getIgnoreFile: z12.object({}),
4756
+ putIgnoreFile: z12.object({
4757
+ content: z12.string()
4584
4758
  }),
4585
- deleteIgnoreFile: z11.object({})
4759
+ deleteIgnoreFile: z12.object({})
4586
4760
  };
4587
4761
  var ignoreTools = {
4588
4762
  getIgnoreFile: {
@@ -4615,11 +4789,11 @@ var ignoreTools = {
4615
4789
  };
4616
4790
 
4617
4791
  // src/mcp/import.ts
4618
- import { z as z12 } from "zod/mini";
4619
- var importOptionsSchema = z12.object({
4620
- target: z12.string(),
4621
- features: z12.optional(z12.array(z12.string())),
4622
- global: z12.optional(z12.boolean())
4792
+ import { z as z13 } from "zod/mini";
4793
+ var importOptionsSchema = z13.object({
4794
+ target: z13.string(),
4795
+ features: z13.optional(z13.array(z13.string())),
4796
+ global: z13.optional(z13.boolean())
4623
4797
  });
4624
4798
  async function executeImport(options) {
4625
4799
  try {
@@ -4643,7 +4817,7 @@ async function executeImport(options) {
4643
4817
  const tool = config.getTargets()[0];
4644
4818
  const logger5 = new ConsoleLogger({ verbose: false, silent: true });
4645
4819
  const importResult = await importFromTool({ config, tool, logger: logger5 });
4646
- return buildSuccessResponse2({ importResult, config, tool });
4820
+ return buildSuccessResponse3({ importResult, config, tool });
4647
4821
  } catch (error) {
4648
4822
  return {
4649
4823
  success: false,
@@ -4651,7 +4825,7 @@ async function executeImport(options) {
4651
4825
  };
4652
4826
  }
4653
4827
  }
4654
- function buildSuccessResponse2(params) {
4828
+ function buildSuccessResponse3(params) {
4655
4829
  const { importResult, config, tool } = params;
4656
4830
  const totalCount = calculateTotalCount(importResult);
4657
4831
  return {
@@ -4691,7 +4865,7 @@ var importTools = {
4691
4865
 
4692
4866
  // src/mcp/mcp.ts
4693
4867
  import { join as join16 } from "path";
4694
- import { z as z13 } from "zod/mini";
4868
+ import { z as z14 } from "zod/mini";
4695
4869
  var maxMcpSizeBytes = 1024 * 1024;
4696
4870
  async function getMcpFile() {
4697
4871
  try {
@@ -4789,11 +4963,11 @@ async function deleteMcpFile() {
4789
4963
  }
4790
4964
  }
4791
4965
  var mcpToolSchemas = {
4792
- getMcpFile: z13.object({}),
4793
- putMcpFile: z13.object({
4794
- content: z13.string()
4966
+ getMcpFile: z14.object({}),
4967
+ putMcpFile: z14.object({
4968
+ content: z14.string()
4795
4969
  }),
4796
- deleteMcpFile: z13.object({})
4970
+ deleteMcpFile: z14.object({})
4797
4971
  };
4798
4972
  var mcpTools = {
4799
4973
  getMcpFile: {
@@ -4827,7 +5001,7 @@ var mcpTools = {
4827
5001
 
4828
5002
  // src/mcp/permissions.ts
4829
5003
  import { join as join17 } from "path";
4830
- import { z as z14 } from "zod/mini";
5004
+ import { z as z15 } from "zod/mini";
4831
5005
  var maxPermissionsSizeBytes = 1024 * 1024;
4832
5006
  async function getPermissionsFile() {
4833
5007
  try {
@@ -4916,11 +5090,11 @@ async function deletePermissionsFile() {
4916
5090
  }
4917
5091
  }
4918
5092
  var permissionsToolSchemas = {
4919
- getPermissionsFile: z14.object({}),
4920
- putPermissionsFile: z14.object({
4921
- content: z14.string()
5093
+ getPermissionsFile: z15.object({}),
5094
+ putPermissionsFile: z15.object({
5095
+ content: z15.string()
4922
5096
  }),
4923
- deletePermissionsFile: z14.object({})
5097
+ deletePermissionsFile: z15.object({})
4924
5098
  };
4925
5099
  var permissionsTools = {
4926
5100
  getPermissionsFile: {
@@ -4954,7 +5128,7 @@ var permissionsTools = {
4954
5128
 
4955
5129
  // src/mcp/rules.ts
4956
5130
  import { basename as basename3, join as join18 } from "path";
4957
- import { z as z15 } from "zod/mini";
5131
+ import { z as z16 } from "zod/mini";
4958
5132
  var logger2 = new ConsoleLogger({ verbose: false, silent: true });
4959
5133
  var maxRuleSizeBytes = 1024 * 1024;
4960
5134
  var maxRulesCount = 1e3;
@@ -5078,17 +5252,17 @@ async function deleteRule({ relativePathFromCwd }) {
5078
5252
  }
5079
5253
  }
5080
5254
  var ruleToolSchemas = {
5081
- listRules: z15.object({}),
5082
- getRule: z15.object({
5083
- relativePathFromCwd: z15.string()
5255
+ listRules: z16.object({}),
5256
+ getRule: z16.object({
5257
+ relativePathFromCwd: z16.string()
5084
5258
  }),
5085
- putRule: z15.object({
5086
- relativePathFromCwd: z15.string(),
5259
+ putRule: z16.object({
5260
+ relativePathFromCwd: z16.string(),
5087
5261
  frontmatter: RulesyncRuleFrontmatterSchema,
5088
- body: z15.string()
5262
+ body: z16.string()
5089
5263
  }),
5090
- deleteRule: z15.object({
5091
- relativePathFromCwd: z15.string()
5264
+ deleteRule: z16.object({
5265
+ relativePathFromCwd: z16.string()
5092
5266
  })
5093
5267
  };
5094
5268
  var ruleTools = {
@@ -5137,7 +5311,7 @@ var ruleTools = {
5137
5311
 
5138
5312
  // src/mcp/skills.ts
5139
5313
  import { basename as basename4, dirname, join as join19 } from "path";
5140
- import { z as z16 } from "zod/mini";
5314
+ import { z as z17 } from "zod/mini";
5141
5315
  var logger3 = new ConsoleLogger({ verbose: false, silent: true });
5142
5316
  var maxSkillSizeBytes = 1024 * 1024;
5143
5317
  var maxSkillsCount = 1e3;
@@ -5310,23 +5484,23 @@ async function deleteSkill({
5310
5484
  );
5311
5485
  }
5312
5486
  }
5313
- var McpSkillFileSchema = z16.object({
5314
- name: z16.string(),
5315
- body: z16.string()
5487
+ var McpSkillFileSchema = z17.object({
5488
+ name: z17.string(),
5489
+ body: z17.string()
5316
5490
  });
5317
5491
  var skillToolSchemas = {
5318
- listSkills: z16.object({}),
5319
- getSkill: z16.object({
5320
- relativeDirPathFromCwd: z16.string()
5492
+ listSkills: z17.object({}),
5493
+ getSkill: z17.object({
5494
+ relativeDirPathFromCwd: z17.string()
5321
5495
  }),
5322
- putSkill: z16.object({
5323
- relativeDirPathFromCwd: z16.string(),
5496
+ putSkill: z17.object({
5497
+ relativeDirPathFromCwd: z17.string(),
5324
5498
  frontmatter: RulesyncSkillFrontmatterSchema,
5325
- body: z16.string(),
5326
- otherFiles: z16.optional(z16.array(McpSkillFileSchema))
5499
+ body: z17.string(),
5500
+ otherFiles: z17.optional(z17.array(McpSkillFileSchema))
5327
5501
  }),
5328
- deleteSkill: z16.object({
5329
- relativeDirPathFromCwd: z16.string()
5502
+ deleteSkill: z17.object({
5503
+ relativeDirPathFromCwd: z17.string()
5330
5504
  })
5331
5505
  };
5332
5506
  var skillTools = {
@@ -5376,7 +5550,7 @@ var skillTools = {
5376
5550
 
5377
5551
  // src/mcp/subagents.ts
5378
5552
  import { basename as basename5, join as join20 } from "path";
5379
- import { z as z17 } from "zod/mini";
5553
+ import { z as z18 } from "zod/mini";
5380
5554
  var logger4 = new ConsoleLogger({ verbose: false, silent: true });
5381
5555
  var maxSubagentSizeBytes = 1024 * 1024;
5382
5556
  var maxSubagentsCount = 1e3;
@@ -5505,17 +5679,17 @@ async function deleteSubagent({ relativePathFromCwd }) {
5505
5679
  }
5506
5680
  }
5507
5681
  var subagentToolSchemas = {
5508
- listSubagents: z17.object({}),
5509
- getSubagent: z17.object({
5510
- relativePathFromCwd: z17.string()
5682
+ listSubagents: z18.object({}),
5683
+ getSubagent: z18.object({
5684
+ relativePathFromCwd: z18.string()
5511
5685
  }),
5512
- putSubagent: z17.object({
5513
- relativePathFromCwd: z17.string(),
5686
+ putSubagent: z18.object({
5687
+ relativePathFromCwd: z18.string(),
5514
5688
  frontmatter: RulesyncSubagentFrontmatterSchema,
5515
- body: z17.string()
5689
+ body: z18.string()
5516
5690
  }),
5517
- deleteSubagent: z17.object({
5518
- relativePathFromCwd: z17.string()
5691
+ deleteSubagent: z18.object({
5692
+ relativePathFromCwd: z18.string()
5519
5693
  })
5520
5694
  };
5521
5695
  var subagentTools = {
@@ -5563,7 +5737,7 @@ var subagentTools = {
5563
5737
  };
5564
5738
 
5565
5739
  // src/mcp/tools.ts
5566
- var rulesyncFeatureSchema = z18.enum([
5740
+ var rulesyncFeatureSchema = z19.enum([
5567
5741
  "rule",
5568
5742
  "command",
5569
5743
  "subagent",
@@ -5573,23 +5747,25 @@ var rulesyncFeatureSchema = z18.enum([
5573
5747
  "permissions",
5574
5748
  "hooks",
5575
5749
  "generate",
5576
- "import"
5750
+ "import",
5751
+ "convert"
5577
5752
  ]);
5578
- var rulesyncOperationSchema = z18.enum(["list", "get", "put", "delete", "run"]);
5579
- var skillFileSchema = z18.object({
5580
- name: z18.string(),
5581
- body: z18.string()
5753
+ var rulesyncOperationSchema = z19.enum(["list", "get", "put", "delete", "run"]);
5754
+ var skillFileSchema = z19.object({
5755
+ name: z19.string(),
5756
+ body: z19.string()
5582
5757
  });
5583
- var rulesyncToolSchema = z18.object({
5758
+ var rulesyncToolSchema = z19.object({
5584
5759
  feature: rulesyncFeatureSchema,
5585
5760
  operation: rulesyncOperationSchema,
5586
- targetPathFromCwd: z18.optional(z18.string()),
5587
- frontmatter: z18.optional(z18.unknown()),
5588
- body: z18.optional(z18.string()),
5589
- otherFiles: z18.optional(z18.array(skillFileSchema)),
5590
- content: z18.optional(z18.string()),
5591
- generateOptions: z18.optional(generateOptionsSchema),
5592
- importOptions: z18.optional(importOptionsSchema)
5761
+ targetPathFromCwd: z19.optional(z19.string()),
5762
+ frontmatter: z19.optional(z19.unknown()),
5763
+ body: z19.optional(z19.string()),
5764
+ otherFiles: z19.optional(z19.array(skillFileSchema)),
5765
+ content: z19.optional(z19.string()),
5766
+ generateOptions: z19.optional(generateOptionsSchema),
5767
+ importOptions: z19.optional(importOptionsSchema),
5768
+ convertOptions: z19.optional(convertOptionsSchema)
5593
5769
  });
5594
5770
  var supportedOperationsByFeature = {
5595
5771
  rule: ["list", "get", "put", "delete"],
@@ -5601,7 +5777,8 @@ var supportedOperationsByFeature = {
5601
5777
  permissions: ["get", "put", "delete"],
5602
5778
  hooks: ["get", "put", "delete"],
5603
5779
  generate: ["run"],
5604
- import: ["run"]
5780
+ import: ["run"],
5781
+ convert: ["run"]
5605
5782
  };
5606
5783
  function assertSupported({
5607
5784
  feature,
@@ -5649,7 +5826,7 @@ function ensureBody({ body, feature, operation }) {
5649
5826
  }
5650
5827
  var rulesyncTool = {
5651
5828
  name: "rulesyncTool",
5652
- description: "Manage Rulesync files through a single MCP tool. Features: rule/command/subagent/skill support list/get/put/delete; ignore/mcp/permissions/hooks support get/put/delete only; generate supports run only; import supports run only. Parameters: list requires no targetPathFromCwd (lists all items); get/delete require targetPathFromCwd; put requires targetPathFromCwd, frontmatter, and body (or content for ignore/mcp/permissions/hooks); generate/run uses generateOptions to configure generation; import/run uses importOptions to configure import.",
5829
+ description: "Manage Rulesync files through a single MCP tool. Features: rule/command/subagent/skill support list/get/put/delete; ignore/mcp/permissions/hooks support get/put/delete only; generate supports run only; import supports run only; convert supports run only. Parameters: list requires no targetPathFromCwd (lists all items); get/delete require targetPathFromCwd; put requires targetPathFromCwd, frontmatter, and body (or content for ignore/mcp/permissions/hooks); generate/run uses generateOptions to configure generation; import/run uses importOptions to configure import; convert/run uses convertOptions to configure conversion.",
5653
5830
  parameters: rulesyncToolSchema,
5654
5831
  execute: async (args) => {
5655
5832
  const parsed = rulesyncToolSchema.parse(args);
@@ -5799,6 +5976,12 @@ var rulesyncTool = {
5799
5976
  }
5800
5977
  return importTools.executeImport.execute(parsed.importOptions);
5801
5978
  }
5979
+ case "convert": {
5980
+ if (!parsed.convertOptions) {
5981
+ throw new Error("convertOptions is required for convert feature");
5982
+ }
5983
+ return convertTools.executeConvert.execute(parsed.convertOptions);
5984
+ }
5802
5985
  default: {
5803
5986
  throw new Error(`Unknown feature: ${parsed.feature}`);
5804
5987
  }
@@ -6252,7 +6435,7 @@ function wrapCommand({
6252
6435
  }
6253
6436
 
6254
6437
  // src/cli/index.ts
6255
- var getVersion = () => "8.9.0";
6438
+ var getVersion = () => "8.11.0";
6256
6439
  function wrapCommand2(name, errorCode, handler) {
6257
6440
  return wrapCommand({ name, errorCode, handler, getVersion });
6258
6441
  }
@@ -6313,6 +6496,21 @@ var main = async () => {
6313
6496
  await importCommand(logger5, options);
6314
6497
  })
6315
6498
  );
6499
+ program.command("convert").description(
6500
+ "Convert configurations from one AI tool to other AI tools without writing .rulesync/ files"
6501
+ ).requiredOption("--from <tool>", "Source tool to convert from (e.g., 'cursor', 'claudecode')").requiredOption(
6502
+ "--to <tools>",
6503
+ "Comma-separated list of destination tools (e.g., 'copilot,claudecode')",
6504
+ parseCommaSeparatedList
6505
+ ).option(
6506
+ "-f, --features <features>",
6507
+ `Comma-separated list of features to convert (${ALL_FEATURES.join(",")}) or '*' for all`,
6508
+ parseCommaSeparatedList
6509
+ ).option("-V, --verbose", "Verbose output").option("-s, --silent", "Suppress all output").option("-g, --global", "Convert for global(user scope) configuration files").option("--dry-run", "Dry run: show changes without writing files").action(
6510
+ wrapCommand2("convert", "CONVERT_FAILED", async (logger5, options) => {
6511
+ await convertCommand(logger5, options);
6512
+ })
6513
+ );
6316
6514
  program.command("mcp").description("Start MCP server for rulesync").action(
6317
6515
  wrapCommand2("mcp", "MCP_FAILED", async (logger5, _options) => {
6318
6516
  await mcpCommand(logger5, { version });