rulesync 7.11.0 → 7.12.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.
@@ -731,10 +731,9 @@ function parseFrontmatter(content, filePath) {
731
731
  body = result.content;
732
732
  } catch (error) {
733
733
  if (filePath) {
734
- throw new Error(
735
- `Failed to parse frontmatter in ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
736
- { cause: error }
737
- );
734
+ throw new Error(`Failed to parse frontmatter in ${filePath}: ${formatError(error)}`, {
735
+ cause: error
736
+ });
738
737
  }
739
738
  throw error;
740
739
  }
@@ -8045,7 +8044,8 @@ var RulesyncSkillFrontmatterSchemaInternal = z24.looseObject({
8045
8044
  targets: z24._default(RulesyncTargetsSchema, ["*"]),
8046
8045
  claudecode: z24.optional(
8047
8046
  z24.looseObject({
8048
- "allowed-tools": z24.optional(z24.array(z24.string()))
8047
+ "allowed-tools": z24.optional(z24.array(z24.string())),
8048
+ model: z24.optional(z24.string())
8049
8049
  })
8050
8050
  ),
8051
8051
  codexcli: z24.optional(
@@ -8481,7 +8481,8 @@ import { z as z27 } from "zod/mini";
8481
8481
  var ClaudecodeSkillFrontmatterSchema = z27.looseObject({
8482
8482
  name: z27.string(),
8483
8483
  description: z27.string(),
8484
- "allowed-tools": z27.optional(z27.array(z27.string()))
8484
+ "allowed-tools": z27.optional(z27.array(z27.string())),
8485
+ model: z27.optional(z27.string())
8485
8486
  });
8486
8487
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8487
8488
  constructor({
@@ -8547,15 +8548,15 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8547
8548
  }
8548
8549
  toRulesyncSkill() {
8549
8550
  const frontmatter = this.getFrontmatter();
8551
+ const claudecodeSection = {
8552
+ ...frontmatter["allowed-tools"] && { "allowed-tools": frontmatter["allowed-tools"] },
8553
+ ...frontmatter.model && { model: frontmatter.model }
8554
+ };
8550
8555
  const rulesyncFrontmatter = {
8551
8556
  name: frontmatter.name,
8552
8557
  description: frontmatter.description,
8553
8558
  targets: ["*"],
8554
- ...frontmatter["allowed-tools"] && {
8555
- claudecode: {
8556
- "allowed-tools": frontmatter["allowed-tools"]
8557
- }
8558
- }
8559
+ ...Object.keys(claudecodeSection).length > 0 && { claudecode: claudecodeSection }
8559
8560
  };
8560
8561
  return new RulesyncSkill({
8561
8562
  baseDir: this.baseDir,
@@ -8577,7 +8578,12 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8577
8578
  const claudecodeFrontmatter = {
8578
8579
  name: rulesyncFrontmatter.name,
8579
8580
  description: rulesyncFrontmatter.description,
8580
- "allowed-tools": rulesyncFrontmatter.claudecode?.["allowed-tools"]
8581
+ ...rulesyncFrontmatter.claudecode?.["allowed-tools"] && {
8582
+ "allowed-tools": rulesyncFrontmatter.claudecode["allowed-tools"]
8583
+ },
8584
+ ...rulesyncFrontmatter.claudecode?.model && {
8585
+ model: rulesyncFrontmatter.claudecode.model
8586
+ }
8581
8587
  };
8582
8588
  const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
8583
8589
  return new _ClaudecodeSkill({
@@ -13254,16 +13260,12 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
13254
13260
  throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
13255
13261
  }
13256
13262
  const relativePath = join96(paths.nonRoot.relativeDirPath, relativeFilePath);
13257
- const fileContent = await readFileContent(join96(baseDir, relativePath));
13258
- const { frontmatter, body: content } = parseFrontmatter(
13259
- fileContent,
13260
- join96(baseDir, relativePath)
13261
- );
13263
+ const filePath = join96(baseDir, relativePath);
13264
+ const fileContent = await readFileContent(filePath);
13265
+ const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
13262
13266
  const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
13263
13267
  if (!result.success) {
13264
- throw new Error(
13265
- `Invalid frontmatter in ${join96(baseDir, relativePath)}: ${formatError(result.error)}`
13266
- );
13268
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
13267
13269
  }
13268
13270
  return new _ClaudecodeRule({
13269
13271
  baseDir,
@@ -13695,7 +13697,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
13695
13697
  const isRoot = relativeFilePath === paths.root.relativeFilePath;
13696
13698
  if (isRoot) {
13697
13699
  const relativePath2 = join99(paths.root.relativeDirPath, paths.root.relativeFilePath);
13698
- const fileContent2 = await readFileContent(join99(baseDir, relativePath2));
13700
+ const filePath2 = join99(baseDir, relativePath2);
13701
+ const fileContent2 = await readFileContent(filePath2);
13699
13702
  return new _CopilotRule({
13700
13703
  baseDir,
13701
13704
  relativeDirPath: paths.root.relativeDirPath,
@@ -13710,16 +13713,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
13710
13713
  throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
13711
13714
  }
13712
13715
  const relativePath = join99(paths.nonRoot.relativeDirPath, relativeFilePath);
13713
- const fileContent = await readFileContent(join99(baseDir, relativePath));
13714
- const { frontmatter, body: content } = parseFrontmatter(
13715
- fileContent,
13716
- join99(baseDir, relativePath)
13717
- );
13716
+ const filePath = join99(baseDir, relativePath);
13717
+ const fileContent = await readFileContent(filePath);
13718
+ const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
13718
13719
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
13719
13720
  if (!result.success) {
13720
- throw new Error(
13721
- `Invalid frontmatter in ${join99(baseDir, relativeFilePath)}: ${formatError(result.error)}`
13722
- );
13721
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
13723
13722
  }
13724
13723
  return new _CopilotRule({
13725
13724
  baseDir,
@@ -15877,6 +15876,14 @@ async function processEmptyFeatureGeneration(params) {
15877
15876
  }
15878
15877
  return { count: totalCount, paths: [], hasDiff };
15879
15878
  }
15879
+ function warnUnsupportedTargets(params) {
15880
+ const { config, supportedTargets, featureName } = params;
15881
+ for (const target of config.getTargets()) {
15882
+ if (!supportedTargets.includes(target) && config.getFeatures(target).includes(featureName)) {
15883
+ logger.warn(`Target '${target}' does not support the feature '${featureName}'. Skipping.`);
15884
+ }
15885
+ }
15886
+ }
15880
15887
  async function checkRulesyncDirExists(params) {
15881
15888
  return fileExists(join114(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
15882
15889
  }
@@ -15914,10 +15921,9 @@ async function generateRulesCore(params) {
15914
15921
  let totalCount = 0;
15915
15922
  const allPaths = [];
15916
15923
  let hasDiff = false;
15917
- const toolTargets = intersection(
15918
- config.getTargets(),
15919
- RulesProcessor.getToolTargets({ global: config.getGlobal() })
15920
- );
15924
+ const supportedTargets = RulesProcessor.getToolTargets({ global: config.getGlobal() });
15925
+ const toolTargets = intersection(config.getTargets(), supportedTargets);
15926
+ warnUnsupportedTargets({ config, supportedTargets, featureName: "rules" });
15921
15927
  for (const baseDir of config.getBaseDirs()) {
15922
15928
  for (const toolTarget of toolTargets) {
15923
15929
  if (!config.getFeatures(toolTarget).includes("rules")) {
@@ -15949,13 +15955,19 @@ async function generateRulesCore(params) {
15949
15955
  }
15950
15956
  async function generateIgnoreCore(params) {
15951
15957
  const { config } = params;
15958
+ const supportedIgnoreTargets = IgnoreProcessor.getToolTargets();
15959
+ warnUnsupportedTargets({
15960
+ config,
15961
+ supportedTargets: supportedIgnoreTargets,
15962
+ featureName: "ignore"
15963
+ });
15952
15964
  if (config.getGlobal()) {
15953
15965
  return { count: 0, paths: [], hasDiff: false };
15954
15966
  }
15955
15967
  let totalCount = 0;
15956
15968
  const allPaths = [];
15957
15969
  let hasDiff = false;
15958
- for (const toolTarget of intersection(config.getTargets(), IgnoreProcessor.getToolTargets())) {
15970
+ for (const toolTarget of intersection(config.getTargets(), supportedIgnoreTargets)) {
15959
15971
  if (!config.getFeatures(toolTarget).includes("ignore")) {
15960
15972
  continue;
15961
15973
  }
@@ -15999,10 +16011,9 @@ async function generateMcpCore(params) {
15999
16011
  let totalCount = 0;
16000
16012
  const allPaths = [];
16001
16013
  let hasDiff = false;
16002
- const toolTargets = intersection(
16003
- config.getTargets(),
16004
- McpProcessor.getToolTargets({ global: config.getGlobal() })
16005
- );
16014
+ const supportedMcpTargets = McpProcessor.getToolTargets({ global: config.getGlobal() });
16015
+ const toolTargets = intersection(config.getTargets(), supportedMcpTargets);
16016
+ warnUnsupportedTargets({ config, supportedTargets: supportedMcpTargets, featureName: "mcp" });
16006
16017
  for (const baseDir of config.getBaseDirs()) {
16007
16018
  for (const toolTarget of toolTargets) {
16008
16019
  if (!config.getFeatures(toolTarget).includes("mcp")) {
@@ -16033,13 +16044,16 @@ async function generateCommandsCore(params) {
16033
16044
  let totalCount = 0;
16034
16045
  const allPaths = [];
16035
16046
  let hasDiff = false;
16036
- const toolTargets = intersection(
16037
- config.getTargets(),
16038
- CommandsProcessor.getToolTargets({
16039
- global: config.getGlobal(),
16040
- includeSimulated: config.getSimulateCommands()
16041
- })
16042
- );
16047
+ const supportedCommandsTargets = CommandsProcessor.getToolTargets({
16048
+ global: config.getGlobal(),
16049
+ includeSimulated: config.getSimulateCommands()
16050
+ });
16051
+ const toolTargets = intersection(config.getTargets(), supportedCommandsTargets);
16052
+ warnUnsupportedTargets({
16053
+ config,
16054
+ supportedTargets: supportedCommandsTargets,
16055
+ featureName: "commands"
16056
+ });
16043
16057
  for (const baseDir of config.getBaseDirs()) {
16044
16058
  for (const toolTarget of toolTargets) {
16045
16059
  if (!config.getFeatures(toolTarget).includes("commands")) {
@@ -16070,13 +16084,16 @@ async function generateSubagentsCore(params) {
16070
16084
  let totalCount = 0;
16071
16085
  const allPaths = [];
16072
16086
  let hasDiff = false;
16073
- const toolTargets = intersection(
16074
- config.getTargets(),
16075
- SubagentsProcessor.getToolTargets({
16076
- global: config.getGlobal(),
16077
- includeSimulated: config.getSimulateSubagents()
16078
- })
16079
- );
16087
+ const supportedSubagentsTargets = SubagentsProcessor.getToolTargets({
16088
+ global: config.getGlobal(),
16089
+ includeSimulated: config.getSimulateSubagents()
16090
+ });
16091
+ const toolTargets = intersection(config.getTargets(), supportedSubagentsTargets);
16092
+ warnUnsupportedTargets({
16093
+ config,
16094
+ supportedTargets: supportedSubagentsTargets,
16095
+ featureName: "subagents"
16096
+ });
16080
16097
  for (const baseDir of config.getBaseDirs()) {
16081
16098
  for (const toolTarget of toolTargets) {
16082
16099
  if (!config.getFeatures(toolTarget).includes("subagents")) {
@@ -16108,13 +16125,16 @@ async function generateSkillsCore(params) {
16108
16125
  const allPaths = [];
16109
16126
  let hasDiff = false;
16110
16127
  const allSkills = [];
16111
- const toolTargets = intersection(
16112
- config.getTargets(),
16113
- SkillsProcessor.getToolTargets({
16114
- global: config.getGlobal(),
16115
- includeSimulated: config.getSimulateSkills()
16116
- })
16117
- );
16128
+ const supportedSkillsTargets = SkillsProcessor.getToolTargets({
16129
+ global: config.getGlobal(),
16130
+ includeSimulated: config.getSimulateSkills()
16131
+ });
16132
+ const toolTargets = intersection(config.getTargets(), supportedSkillsTargets);
16133
+ warnUnsupportedTargets({
16134
+ config,
16135
+ supportedTargets: supportedSkillsTargets,
16136
+ featureName: "skills"
16137
+ });
16118
16138
  for (const baseDir of config.getBaseDirs()) {
16119
16139
  for (const toolTarget of toolTargets) {
16120
16140
  if (!config.getFeatures(toolTarget).includes("skills")) {
@@ -16150,10 +16170,9 @@ async function generateHooksCore(params) {
16150
16170
  let totalCount = 0;
16151
16171
  const allPaths = [];
16152
16172
  let hasDiff = false;
16153
- const toolTargets = intersection(
16154
- config.getTargets(),
16155
- HooksProcessor.getToolTargets({ global: config.getGlobal() })
16156
- );
16173
+ const supportedHooksTargets = HooksProcessor.getToolTargets({ global: config.getGlobal() });
16174
+ const toolTargets = intersection(config.getTargets(), supportedHooksTargets);
16175
+ warnUnsupportedTargets({ config, supportedTargets: supportedHooksTargets, featureName: "hooks" });
16157
16176
  for (const baseDir of config.getBaseDirs()) {
16158
16177
  for (const toolTarget of toolTargets) {
16159
16178
  if (!config.getFeatures(toolTarget).includes("hooks")) {
@@ -16225,6 +16244,7 @@ async function importRulesCore(params) {
16225
16244
  });
16226
16245
  const toolFiles = await rulesProcessor.loadToolFiles();
16227
16246
  if (toolFiles.length === 0) {
16247
+ logger.warn(`No rule files found for ${tool}. Skipping import.`);
16228
16248
  return 0;
16229
16249
  }
16230
16250
  const rulesyncFiles = await rulesProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16252,6 +16272,7 @@ async function importIgnoreCore(params) {
16252
16272
  });
16253
16273
  const toolFiles = await ignoreProcessor.loadToolFiles();
16254
16274
  if (toolFiles.length === 0) {
16275
+ logger.warn(`No ignore files found for ${tool}. Skipping import.`);
16255
16276
  return 0;
16256
16277
  }
16257
16278
  const rulesyncFiles = await ignoreProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16281,6 +16302,7 @@ async function importMcpCore(params) {
16281
16302
  });
16282
16303
  const toolFiles = await mcpProcessor.loadToolFiles();
16283
16304
  if (toolFiles.length === 0) {
16305
+ logger.warn(`No MCP files found for ${tool}. Skipping import.`);
16284
16306
  return 0;
16285
16307
  }
16286
16308
  const rulesyncFiles = await mcpProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16307,6 +16329,7 @@ async function importCommandsCore(params) {
16307
16329
  });
16308
16330
  const toolFiles = await commandsProcessor.loadToolFiles();
16309
16331
  if (toolFiles.length === 0) {
16332
+ logger.warn(`No command files found for ${tool}. Skipping import.`);
16310
16333
  return 0;
16311
16334
  }
16312
16335
  const rulesyncFiles = await commandsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16333,6 +16356,7 @@ async function importSubagentsCore(params) {
16333
16356
  });
16334
16357
  const toolFiles = await subagentsProcessor.loadToolFiles();
16335
16358
  if (toolFiles.length === 0) {
16359
+ logger.warn(`No subagent files found for ${tool}. Skipping import.`);
16336
16360
  return 0;
16337
16361
  }
16338
16362
  const rulesyncFiles = await subagentsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16359,6 +16383,7 @@ async function importSkillsCore(params) {
16359
16383
  });
16360
16384
  const toolDirs = await skillsProcessor.loadToolDirs();
16361
16385
  if (toolDirs.length === 0) {
16386
+ logger.warn(`No skill directories found for ${tool}. Skipping import.`);
16362
16387
  return 0;
16363
16388
  }
16364
16389
  const rulesyncDirs = await skillsProcessor.convertToolDirsToRulesyncDirs(toolDirs);
@@ -16390,6 +16415,7 @@ async function importHooksCore(params) {
16390
16415
  });
16391
16416
  const toolFiles = await hooksProcessor.loadToolFiles();
16392
16417
  if (toolFiles.length === 0) {
16418
+ logger.warn(`No hooks files found for ${tool}. Skipping import.`);
16393
16419
  return 0;
16394
16420
  }
16395
16421
  const rulesyncFiles = await hooksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -433,10 +433,9 @@ function parseFrontmatter(content, filePath) {
433
433
  body = result.content;
434
434
  } catch (error) {
435
435
  if (filePath) {
436
- throw new Error(
437
- `Failed to parse frontmatter in ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
438
- { cause: error }
439
- );
436
+ throw new Error(`Failed to parse frontmatter in ${filePath}: ${formatError(error)}`, {
437
+ cause: error
438
+ });
440
439
  }
441
440
  throw error;
442
441
  }
@@ -7780,7 +7779,8 @@ var RulesyncSkillFrontmatterSchemaInternal = import_mini23.z.looseObject({
7780
7779
  targets: import_mini23.z._default(RulesyncTargetsSchema, ["*"]),
7781
7780
  claudecode: import_mini23.z.optional(
7782
7781
  import_mini23.z.looseObject({
7783
- "allowed-tools": import_mini23.z.optional(import_mini23.z.array(import_mini23.z.string()))
7782
+ "allowed-tools": import_mini23.z.optional(import_mini23.z.array(import_mini23.z.string())),
7783
+ model: import_mini23.z.optional(import_mini23.z.string())
7784
7784
  })
7785
7785
  ),
7786
7786
  codexcli: import_mini23.z.optional(
@@ -8216,7 +8216,8 @@ var import_mini26 = require("zod/mini");
8216
8216
  var ClaudecodeSkillFrontmatterSchema = import_mini26.z.looseObject({
8217
8217
  name: import_mini26.z.string(),
8218
8218
  description: import_mini26.z.string(),
8219
- "allowed-tools": import_mini26.z.optional(import_mini26.z.array(import_mini26.z.string()))
8219
+ "allowed-tools": import_mini26.z.optional(import_mini26.z.array(import_mini26.z.string())),
8220
+ model: import_mini26.z.optional(import_mini26.z.string())
8220
8221
  });
8221
8222
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8222
8223
  constructor({
@@ -8282,15 +8283,15 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8282
8283
  }
8283
8284
  toRulesyncSkill() {
8284
8285
  const frontmatter = this.getFrontmatter();
8286
+ const claudecodeSection = {
8287
+ ...frontmatter["allowed-tools"] && { "allowed-tools": frontmatter["allowed-tools"] },
8288
+ ...frontmatter.model && { model: frontmatter.model }
8289
+ };
8285
8290
  const rulesyncFrontmatter = {
8286
8291
  name: frontmatter.name,
8287
8292
  description: frontmatter.description,
8288
8293
  targets: ["*"],
8289
- ...frontmatter["allowed-tools"] && {
8290
- claudecode: {
8291
- "allowed-tools": frontmatter["allowed-tools"]
8292
- }
8293
- }
8294
+ ...Object.keys(claudecodeSection).length > 0 && { claudecode: claudecodeSection }
8294
8295
  };
8295
8296
  return new RulesyncSkill({
8296
8297
  baseDir: this.baseDir,
@@ -8312,7 +8313,12 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8312
8313
  const claudecodeFrontmatter = {
8313
8314
  name: rulesyncFrontmatter.name,
8314
8315
  description: rulesyncFrontmatter.description,
8315
- "allowed-tools": rulesyncFrontmatter.claudecode?.["allowed-tools"]
8316
+ ...rulesyncFrontmatter.claudecode?.["allowed-tools"] && {
8317
+ "allowed-tools": rulesyncFrontmatter.claudecode["allowed-tools"]
8318
+ },
8319
+ ...rulesyncFrontmatter.claudecode?.model && {
8320
+ model: rulesyncFrontmatter.claudecode.model
8321
+ }
8316
8322
  };
8317
8323
  const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
8318
8324
  return new _ClaudecodeSkill({
@@ -12989,16 +12995,12 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
12989
12995
  throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
12990
12996
  }
12991
12997
  const relativePath = (0, import_node_path96.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
12992
- const fileContent = await readFileContent((0, import_node_path96.join)(baseDir, relativePath));
12993
- const { frontmatter, body: content } = parseFrontmatter(
12994
- fileContent,
12995
- (0, import_node_path96.join)(baseDir, relativePath)
12996
- );
12998
+ const filePath = (0, import_node_path96.join)(baseDir, relativePath);
12999
+ const fileContent = await readFileContent(filePath);
13000
+ const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
12997
13001
  const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
12998
13002
  if (!result.success) {
12999
- throw new Error(
13000
- `Invalid frontmatter in ${(0, import_node_path96.join)(baseDir, relativePath)}: ${formatError(result.error)}`
13001
- );
13003
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
13002
13004
  }
13003
13005
  return new _ClaudecodeRule({
13004
13006
  baseDir,
@@ -13430,7 +13432,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
13430
13432
  const isRoot = relativeFilePath === paths.root.relativeFilePath;
13431
13433
  if (isRoot) {
13432
13434
  const relativePath2 = (0, import_node_path99.join)(paths.root.relativeDirPath, paths.root.relativeFilePath);
13433
- const fileContent2 = await readFileContent((0, import_node_path99.join)(baseDir, relativePath2));
13435
+ const filePath2 = (0, import_node_path99.join)(baseDir, relativePath2);
13436
+ const fileContent2 = await readFileContent(filePath2);
13434
13437
  return new _CopilotRule({
13435
13438
  baseDir,
13436
13439
  relativeDirPath: paths.root.relativeDirPath,
@@ -13445,16 +13448,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
13445
13448
  throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
13446
13449
  }
13447
13450
  const relativePath = (0, import_node_path99.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
13448
- const fileContent = await readFileContent((0, import_node_path99.join)(baseDir, relativePath));
13449
- const { frontmatter, body: content } = parseFrontmatter(
13450
- fileContent,
13451
- (0, import_node_path99.join)(baseDir, relativePath)
13452
- );
13451
+ const filePath = (0, import_node_path99.join)(baseDir, relativePath);
13452
+ const fileContent = await readFileContent(filePath);
13453
+ const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
13453
13454
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
13454
13455
  if (!result.success) {
13455
- throw new Error(
13456
- `Invalid frontmatter in ${(0, import_node_path99.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
13457
- );
13456
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
13458
13457
  }
13459
13458
  return new _CopilotRule({
13460
13459
  baseDir,
@@ -16839,6 +16838,14 @@ async function processEmptyFeatureGeneration(params) {
16839
16838
  }
16840
16839
  return { count: totalCount, paths: [], hasDiff };
16841
16840
  }
16841
+ function warnUnsupportedTargets(params) {
16842
+ const { config, supportedTargets, featureName } = params;
16843
+ for (const target of config.getTargets()) {
16844
+ if (!supportedTargets.includes(target) && config.getFeatures(target).includes(featureName)) {
16845
+ logger.warn(`Target '${target}' does not support the feature '${featureName}'. Skipping.`);
16846
+ }
16847
+ }
16848
+ }
16842
16849
  async function checkRulesyncDirExists(params) {
16843
16850
  return fileExists((0, import_node_path116.join)(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
16844
16851
  }
@@ -16876,10 +16883,9 @@ async function generateRulesCore(params) {
16876
16883
  let totalCount = 0;
16877
16884
  const allPaths = [];
16878
16885
  let hasDiff = false;
16879
- const toolTargets = (0, import_es_toolkit4.intersection)(
16880
- config.getTargets(),
16881
- RulesProcessor.getToolTargets({ global: config.getGlobal() })
16882
- );
16886
+ const supportedTargets = RulesProcessor.getToolTargets({ global: config.getGlobal() });
16887
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedTargets);
16888
+ warnUnsupportedTargets({ config, supportedTargets, featureName: "rules" });
16883
16889
  for (const baseDir of config.getBaseDirs()) {
16884
16890
  for (const toolTarget of toolTargets) {
16885
16891
  if (!config.getFeatures(toolTarget).includes("rules")) {
@@ -16911,13 +16917,19 @@ async function generateRulesCore(params) {
16911
16917
  }
16912
16918
  async function generateIgnoreCore(params) {
16913
16919
  const { config } = params;
16920
+ const supportedIgnoreTargets = IgnoreProcessor.getToolTargets();
16921
+ warnUnsupportedTargets({
16922
+ config,
16923
+ supportedTargets: supportedIgnoreTargets,
16924
+ featureName: "ignore"
16925
+ });
16914
16926
  if (config.getGlobal()) {
16915
16927
  return { count: 0, paths: [], hasDiff: false };
16916
16928
  }
16917
16929
  let totalCount = 0;
16918
16930
  const allPaths = [];
16919
16931
  let hasDiff = false;
16920
- for (const toolTarget of (0, import_es_toolkit4.intersection)(config.getTargets(), IgnoreProcessor.getToolTargets())) {
16932
+ for (const toolTarget of (0, import_es_toolkit4.intersection)(config.getTargets(), supportedIgnoreTargets)) {
16921
16933
  if (!config.getFeatures(toolTarget).includes("ignore")) {
16922
16934
  continue;
16923
16935
  }
@@ -16961,10 +16973,9 @@ async function generateMcpCore(params) {
16961
16973
  let totalCount = 0;
16962
16974
  const allPaths = [];
16963
16975
  let hasDiff = false;
16964
- const toolTargets = (0, import_es_toolkit4.intersection)(
16965
- config.getTargets(),
16966
- McpProcessor.getToolTargets({ global: config.getGlobal() })
16967
- );
16976
+ const supportedMcpTargets = McpProcessor.getToolTargets({ global: config.getGlobal() });
16977
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedMcpTargets);
16978
+ warnUnsupportedTargets({ config, supportedTargets: supportedMcpTargets, featureName: "mcp" });
16968
16979
  for (const baseDir of config.getBaseDirs()) {
16969
16980
  for (const toolTarget of toolTargets) {
16970
16981
  if (!config.getFeatures(toolTarget).includes("mcp")) {
@@ -16995,13 +17006,16 @@ async function generateCommandsCore(params) {
16995
17006
  let totalCount = 0;
16996
17007
  const allPaths = [];
16997
17008
  let hasDiff = false;
16998
- const toolTargets = (0, import_es_toolkit4.intersection)(
16999
- config.getTargets(),
17000
- CommandsProcessor.getToolTargets({
17001
- global: config.getGlobal(),
17002
- includeSimulated: config.getSimulateCommands()
17003
- })
17004
- );
17009
+ const supportedCommandsTargets = CommandsProcessor.getToolTargets({
17010
+ global: config.getGlobal(),
17011
+ includeSimulated: config.getSimulateCommands()
17012
+ });
17013
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedCommandsTargets);
17014
+ warnUnsupportedTargets({
17015
+ config,
17016
+ supportedTargets: supportedCommandsTargets,
17017
+ featureName: "commands"
17018
+ });
17005
17019
  for (const baseDir of config.getBaseDirs()) {
17006
17020
  for (const toolTarget of toolTargets) {
17007
17021
  if (!config.getFeatures(toolTarget).includes("commands")) {
@@ -17032,13 +17046,16 @@ async function generateSubagentsCore(params) {
17032
17046
  let totalCount = 0;
17033
17047
  const allPaths = [];
17034
17048
  let hasDiff = false;
17035
- const toolTargets = (0, import_es_toolkit4.intersection)(
17036
- config.getTargets(),
17037
- SubagentsProcessor.getToolTargets({
17038
- global: config.getGlobal(),
17039
- includeSimulated: config.getSimulateSubagents()
17040
- })
17041
- );
17049
+ const supportedSubagentsTargets = SubagentsProcessor.getToolTargets({
17050
+ global: config.getGlobal(),
17051
+ includeSimulated: config.getSimulateSubagents()
17052
+ });
17053
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedSubagentsTargets);
17054
+ warnUnsupportedTargets({
17055
+ config,
17056
+ supportedTargets: supportedSubagentsTargets,
17057
+ featureName: "subagents"
17058
+ });
17042
17059
  for (const baseDir of config.getBaseDirs()) {
17043
17060
  for (const toolTarget of toolTargets) {
17044
17061
  if (!config.getFeatures(toolTarget).includes("subagents")) {
@@ -17070,13 +17087,16 @@ async function generateSkillsCore(params) {
17070
17087
  const allPaths = [];
17071
17088
  let hasDiff = false;
17072
17089
  const allSkills = [];
17073
- const toolTargets = (0, import_es_toolkit4.intersection)(
17074
- config.getTargets(),
17075
- SkillsProcessor.getToolTargets({
17076
- global: config.getGlobal(),
17077
- includeSimulated: config.getSimulateSkills()
17078
- })
17079
- );
17090
+ const supportedSkillsTargets = SkillsProcessor.getToolTargets({
17091
+ global: config.getGlobal(),
17092
+ includeSimulated: config.getSimulateSkills()
17093
+ });
17094
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedSkillsTargets);
17095
+ warnUnsupportedTargets({
17096
+ config,
17097
+ supportedTargets: supportedSkillsTargets,
17098
+ featureName: "skills"
17099
+ });
17080
17100
  for (const baseDir of config.getBaseDirs()) {
17081
17101
  for (const toolTarget of toolTargets) {
17082
17102
  if (!config.getFeatures(toolTarget).includes("skills")) {
@@ -17112,10 +17132,9 @@ async function generateHooksCore(params) {
17112
17132
  let totalCount = 0;
17113
17133
  const allPaths = [];
17114
17134
  let hasDiff = false;
17115
- const toolTargets = (0, import_es_toolkit4.intersection)(
17116
- config.getTargets(),
17117
- HooksProcessor.getToolTargets({ global: config.getGlobal() })
17118
- );
17135
+ const supportedHooksTargets = HooksProcessor.getToolTargets({ global: config.getGlobal() });
17136
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedHooksTargets);
17137
+ warnUnsupportedTargets({ config, supportedTargets: supportedHooksTargets, featureName: "hooks" });
17119
17138
  for (const baseDir of config.getBaseDirs()) {
17120
17139
  for (const toolTarget of toolTargets) {
17121
17140
  if (!config.getFeatures(toolTarget).includes("hooks")) {
@@ -17291,7 +17310,7 @@ var RULESYNC_HEADER = "# Generated by Rulesync";
17291
17310
  var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
17292
17311
  var RULESYNC_IGNORE_ENTRIES = [
17293
17312
  // Rulesync curated (fetched) skills
17294
- ".rulesync/skills/.curated/",
17313
+ `${RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH}/`,
17295
17314
  // AGENTS.md
17296
17315
  "**/AGENTS.md",
17297
17316
  "**/.agents/",
@@ -17511,6 +17530,7 @@ async function importRulesCore(params) {
17511
17530
  });
17512
17531
  const toolFiles = await rulesProcessor.loadToolFiles();
17513
17532
  if (toolFiles.length === 0) {
17533
+ logger.warn(`No rule files found for ${tool}. Skipping import.`);
17514
17534
  return 0;
17515
17535
  }
17516
17536
  const rulesyncFiles = await rulesProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -17538,6 +17558,7 @@ async function importIgnoreCore(params) {
17538
17558
  });
17539
17559
  const toolFiles = await ignoreProcessor.loadToolFiles();
17540
17560
  if (toolFiles.length === 0) {
17561
+ logger.warn(`No ignore files found for ${tool}. Skipping import.`);
17541
17562
  return 0;
17542
17563
  }
17543
17564
  const rulesyncFiles = await ignoreProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -17567,6 +17588,7 @@ async function importMcpCore(params) {
17567
17588
  });
17568
17589
  const toolFiles = await mcpProcessor.loadToolFiles();
17569
17590
  if (toolFiles.length === 0) {
17591
+ logger.warn(`No MCP files found for ${tool}. Skipping import.`);
17570
17592
  return 0;
17571
17593
  }
17572
17594
  const rulesyncFiles = await mcpProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -17593,6 +17615,7 @@ async function importCommandsCore(params) {
17593
17615
  });
17594
17616
  const toolFiles = await commandsProcessor.loadToolFiles();
17595
17617
  if (toolFiles.length === 0) {
17618
+ logger.warn(`No command files found for ${tool}. Skipping import.`);
17596
17619
  return 0;
17597
17620
  }
17598
17621
  const rulesyncFiles = await commandsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -17619,6 +17642,7 @@ async function importSubagentsCore(params) {
17619
17642
  });
17620
17643
  const toolFiles = await subagentsProcessor.loadToolFiles();
17621
17644
  if (toolFiles.length === 0) {
17645
+ logger.warn(`No subagent files found for ${tool}. Skipping import.`);
17622
17646
  return 0;
17623
17647
  }
17624
17648
  const rulesyncFiles = await subagentsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -17645,6 +17669,7 @@ async function importSkillsCore(params) {
17645
17669
  });
17646
17670
  const toolDirs = await skillsProcessor.loadToolDirs();
17647
17671
  if (toolDirs.length === 0) {
17672
+ logger.warn(`No skill directories found for ${tool}. Skipping import.`);
17648
17673
  return 0;
17649
17674
  }
17650
17675
  const rulesyncDirs = await skillsProcessor.convertToolDirsToRulesyncDirs(toolDirs);
@@ -17676,6 +17701,7 @@ async function importHooksCore(params) {
17676
17701
  });
17677
17702
  const toolFiles = await hooksProcessor.loadToolFiles();
17678
17703
  if (toolFiles.length === 0) {
17704
+ logger.warn(`No hooks files found for ${tool}. Skipping import.`);
17679
17705
  return 0;
17680
17706
  }
17681
17707
  const rulesyncFiles = await hooksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -18069,15 +18095,22 @@ function normalizeSourceKey(source) {
18069
18095
  "https://www.github.com/",
18070
18096
  "https://github.com/",
18071
18097
  "http://www.github.com/",
18072
- "http://github.com/"
18098
+ "http://github.com/",
18099
+ "https://www.gitlab.com/",
18100
+ "https://gitlab.com/",
18101
+ "http://www.gitlab.com/",
18102
+ "http://gitlab.com/"
18073
18103
  ]) {
18074
18104
  if (key.toLowerCase().startsWith(prefix)) {
18075
18105
  key = key.substring(prefix.length);
18076
18106
  break;
18077
18107
  }
18078
18108
  }
18079
- if (key.startsWith("github:")) {
18080
- key = key.substring("github:".length);
18109
+ for (const provider of ["github:", "gitlab:"]) {
18110
+ if (key.startsWith(provider)) {
18111
+ key = key.substring(provider.length);
18112
+ break;
18113
+ }
18081
18114
  }
18082
18115
  key = key.replace(/\/+$/, "");
18083
18116
  key = key.replace(/\.git$/, "");
@@ -18161,10 +18194,9 @@ async function resolveAndFetchSources(params) {
18161
18194
  allFetchedSkillNames.add(name);
18162
18195
  }
18163
18196
  } catch (error) {
18197
+ logger.error(`Failed to fetch source "${sourceEntry.source}": ${formatError(error)}`);
18164
18198
  if (error instanceof GitHubClientError) {
18165
18199
  logGitHubAuthHints(error);
18166
- } else {
18167
- logger.error(`Failed to fetch source "${sourceEntry.source}": ${formatError(error)}`);
18168
18200
  }
18169
18201
  }
18170
18202
  }
@@ -18199,7 +18231,8 @@ async function fetchSource(params) {
18199
18231
  let { lock } = params;
18200
18232
  const parsed = parseSource(sourceEntry.source);
18201
18233
  if (parsed.provider === "gitlab") {
18202
- throw new Error("GitLab sources are not yet supported.");
18234
+ logger.warn(`GitLab sources are not yet supported. Skipping "${sourceEntry.source}".`);
18235
+ return { skillCount: 0, fetchedSkillNames: [], updatedLock: lock };
18203
18236
  }
18204
18237
  const sourceKey = sourceEntry.source;
18205
18238
  const locked = getLockedSource(lock, sourceKey);
@@ -20161,7 +20194,7 @@ async function updateCommand(currentVersion, options) {
20161
20194
  }
20162
20195
 
20163
20196
  // src/cli/index.ts
20164
- var getVersion = () => "7.11.0";
20197
+ var getVersion = () => "7.12.0";
20165
20198
  var main = async () => {
20166
20199
  const program = new import_commander.Command();
20167
20200
  const version = getVersion();
package/dist/cli/index.js CHANGED
@@ -60,7 +60,7 @@ import {
60
60
  removeTempDirectory,
61
61
  stringifyFrontmatter,
62
62
  writeFileContent
63
- } from "../chunk-T5MWTRJM.js";
63
+ } from "../chunk-WAWBAZPA.js";
64
64
 
65
65
  // src/cli/index.ts
66
66
  import { Command } from "commander";
@@ -1142,7 +1142,7 @@ var RULESYNC_HEADER = "# Generated by Rulesync";
1142
1142
  var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
1143
1143
  var RULESYNC_IGNORE_ENTRIES = [
1144
1144
  // Rulesync curated (fetched) skills
1145
- ".rulesync/skills/.curated/",
1145
+ `${RULESYNC_CURATED_SKILLS_RELATIVE_DIR_PATH}/`,
1146
1146
  // AGENTS.md
1147
1147
  "**/AGENTS.md",
1148
1148
  "**/.agents/",
@@ -1708,15 +1708,22 @@ function normalizeSourceKey(source) {
1708
1708
  "https://www.github.com/",
1709
1709
  "https://github.com/",
1710
1710
  "http://www.github.com/",
1711
- "http://github.com/"
1711
+ "http://github.com/",
1712
+ "https://www.gitlab.com/",
1713
+ "https://gitlab.com/",
1714
+ "http://www.gitlab.com/",
1715
+ "http://gitlab.com/"
1712
1716
  ]) {
1713
1717
  if (key.toLowerCase().startsWith(prefix)) {
1714
1718
  key = key.substring(prefix.length);
1715
1719
  break;
1716
1720
  }
1717
1721
  }
1718
- if (key.startsWith("github:")) {
1719
- key = key.substring("github:".length);
1722
+ for (const provider of ["github:", "gitlab:"]) {
1723
+ if (key.startsWith(provider)) {
1724
+ key = key.substring(provider.length);
1725
+ break;
1726
+ }
1720
1727
  }
1721
1728
  key = key.replace(/\/+$/, "");
1722
1729
  key = key.replace(/\.git$/, "");
@@ -1800,10 +1807,9 @@ async function resolveAndFetchSources(params) {
1800
1807
  allFetchedSkillNames.add(name);
1801
1808
  }
1802
1809
  } catch (error) {
1810
+ logger.error(`Failed to fetch source "${sourceEntry.source}": ${formatError(error)}`);
1803
1811
  if (error instanceof GitHubClientError) {
1804
1812
  logGitHubAuthHints(error);
1805
- } else {
1806
- logger.error(`Failed to fetch source "${sourceEntry.source}": ${formatError(error)}`);
1807
1813
  }
1808
1814
  }
1809
1815
  }
@@ -1838,7 +1844,8 @@ async function fetchSource(params) {
1838
1844
  let { lock } = params;
1839
1845
  const parsed = parseSource(sourceEntry.source);
1840
1846
  if (parsed.provider === "gitlab") {
1841
- throw new Error("GitLab sources are not yet supported.");
1847
+ logger.warn(`GitLab sources are not yet supported. Skipping "${sourceEntry.source}".`);
1848
+ return { skillCount: 0, fetchedSkillNames: [], updatedLock: lock };
1842
1849
  }
1843
1850
  const sourceKey = sourceEntry.source;
1844
1851
  const locked = getLockedSource(lock, sourceKey);
@@ -3800,7 +3807,7 @@ async function updateCommand(currentVersion, options) {
3800
3807
  }
3801
3808
 
3802
3809
  // src/cli/index.ts
3803
- var getVersion = () => "7.11.0";
3810
+ var getVersion = () => "7.12.0";
3804
3811
  var main = async () => {
3805
3812
  const program = new Command();
3806
3813
  const version = getVersion();
package/dist/index.cjs CHANGED
@@ -759,10 +759,9 @@ function parseFrontmatter(content, filePath) {
759
759
  body = result.content;
760
760
  } catch (error) {
761
761
  if (filePath) {
762
- throw new Error(
763
- `Failed to parse frontmatter in ${filePath}: ${error instanceof Error ? error.message : String(error)}`,
764
- { cause: error }
765
- );
762
+ throw new Error(`Failed to parse frontmatter in ${filePath}: ${formatError(error)}`, {
763
+ cause: error
764
+ });
766
765
  }
767
766
  throw error;
768
767
  }
@@ -8073,7 +8072,8 @@ var RulesyncSkillFrontmatterSchemaInternal = import_mini24.z.looseObject({
8073
8072
  targets: import_mini24.z._default(RulesyncTargetsSchema, ["*"]),
8074
8073
  claudecode: import_mini24.z.optional(
8075
8074
  import_mini24.z.looseObject({
8076
- "allowed-tools": import_mini24.z.optional(import_mini24.z.array(import_mini24.z.string()))
8075
+ "allowed-tools": import_mini24.z.optional(import_mini24.z.array(import_mini24.z.string())),
8076
+ model: import_mini24.z.optional(import_mini24.z.string())
8077
8077
  })
8078
8078
  ),
8079
8079
  codexcli: import_mini24.z.optional(
@@ -8509,7 +8509,8 @@ var import_mini27 = require("zod/mini");
8509
8509
  var ClaudecodeSkillFrontmatterSchema = import_mini27.z.looseObject({
8510
8510
  name: import_mini27.z.string(),
8511
8511
  description: import_mini27.z.string(),
8512
- "allowed-tools": import_mini27.z.optional(import_mini27.z.array(import_mini27.z.string()))
8512
+ "allowed-tools": import_mini27.z.optional(import_mini27.z.array(import_mini27.z.string())),
8513
+ model: import_mini27.z.optional(import_mini27.z.string())
8513
8514
  });
8514
8515
  var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8515
8516
  constructor({
@@ -8575,15 +8576,15 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8575
8576
  }
8576
8577
  toRulesyncSkill() {
8577
8578
  const frontmatter = this.getFrontmatter();
8579
+ const claudecodeSection = {
8580
+ ...frontmatter["allowed-tools"] && { "allowed-tools": frontmatter["allowed-tools"] },
8581
+ ...frontmatter.model && { model: frontmatter.model }
8582
+ };
8578
8583
  const rulesyncFrontmatter = {
8579
8584
  name: frontmatter.name,
8580
8585
  description: frontmatter.description,
8581
8586
  targets: ["*"],
8582
- ...frontmatter["allowed-tools"] && {
8583
- claudecode: {
8584
- "allowed-tools": frontmatter["allowed-tools"]
8585
- }
8586
- }
8587
+ ...Object.keys(claudecodeSection).length > 0 && { claudecode: claudecodeSection }
8587
8588
  };
8588
8589
  return new RulesyncSkill({
8589
8590
  baseDir: this.baseDir,
@@ -8605,7 +8606,12 @@ var ClaudecodeSkill = class _ClaudecodeSkill extends ToolSkill {
8605
8606
  const claudecodeFrontmatter = {
8606
8607
  name: rulesyncFrontmatter.name,
8607
8608
  description: rulesyncFrontmatter.description,
8608
- "allowed-tools": rulesyncFrontmatter.claudecode?.["allowed-tools"]
8609
+ ...rulesyncFrontmatter.claudecode?.["allowed-tools"] && {
8610
+ "allowed-tools": rulesyncFrontmatter.claudecode["allowed-tools"]
8611
+ },
8612
+ ...rulesyncFrontmatter.claudecode?.model && {
8613
+ model: rulesyncFrontmatter.claudecode.model
8614
+ }
8609
8615
  };
8610
8616
  const settablePaths = _ClaudecodeSkill.getSettablePaths({ global });
8611
8617
  return new _ClaudecodeSkill({
@@ -13282,16 +13288,12 @@ var ClaudecodeRule = class _ClaudecodeRule extends ToolRule {
13282
13288
  throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
13283
13289
  }
13284
13290
  const relativePath = (0, import_node_path97.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
13285
- const fileContent = await readFileContent((0, import_node_path97.join)(baseDir, relativePath));
13286
- const { frontmatter, body: content } = parseFrontmatter(
13287
- fileContent,
13288
- (0, import_node_path97.join)(baseDir, relativePath)
13289
- );
13291
+ const filePath = (0, import_node_path97.join)(baseDir, relativePath);
13292
+ const fileContent = await readFileContent(filePath);
13293
+ const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
13290
13294
  const result = ClaudecodeRuleFrontmatterSchema.safeParse(frontmatter);
13291
13295
  if (!result.success) {
13292
- throw new Error(
13293
- `Invalid frontmatter in ${(0, import_node_path97.join)(baseDir, relativePath)}: ${formatError(result.error)}`
13294
- );
13296
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
13295
13297
  }
13296
13298
  return new _ClaudecodeRule({
13297
13299
  baseDir,
@@ -13723,7 +13725,8 @@ var CopilotRule = class _CopilotRule extends ToolRule {
13723
13725
  const isRoot = relativeFilePath === paths.root.relativeFilePath;
13724
13726
  if (isRoot) {
13725
13727
  const relativePath2 = (0, import_node_path100.join)(paths.root.relativeDirPath, paths.root.relativeFilePath);
13726
- const fileContent2 = await readFileContent((0, import_node_path100.join)(baseDir, relativePath2));
13728
+ const filePath2 = (0, import_node_path100.join)(baseDir, relativePath2);
13729
+ const fileContent2 = await readFileContent(filePath2);
13727
13730
  return new _CopilotRule({
13728
13731
  baseDir,
13729
13732
  relativeDirPath: paths.root.relativeDirPath,
@@ -13738,16 +13741,12 @@ var CopilotRule = class _CopilotRule extends ToolRule {
13738
13741
  throw new Error(`nonRoot path is not set for ${relativeFilePath}`);
13739
13742
  }
13740
13743
  const relativePath = (0, import_node_path100.join)(paths.nonRoot.relativeDirPath, relativeFilePath);
13741
- const fileContent = await readFileContent((0, import_node_path100.join)(baseDir, relativePath));
13742
- const { frontmatter, body: content } = parseFrontmatter(
13743
- fileContent,
13744
- (0, import_node_path100.join)(baseDir, relativePath)
13745
- );
13744
+ const filePath = (0, import_node_path100.join)(baseDir, relativePath);
13745
+ const fileContent = await readFileContent(filePath);
13746
+ const { frontmatter, body: content } = parseFrontmatter(fileContent, filePath);
13746
13747
  const result = CopilotRuleFrontmatterSchema.safeParse(frontmatter);
13747
13748
  if (!result.success) {
13748
- throw new Error(
13749
- `Invalid frontmatter in ${(0, import_node_path100.join)(baseDir, relativeFilePath)}: ${formatError(result.error)}`
13750
- );
13749
+ throw new Error(`Invalid frontmatter in ${filePath}: ${formatError(result.error)}`);
13751
13750
  }
13752
13751
  return new _CopilotRule({
13753
13752
  baseDir,
@@ -15905,6 +15904,14 @@ async function processEmptyFeatureGeneration(params) {
15905
15904
  }
15906
15905
  return { count: totalCount, paths: [], hasDiff };
15907
15906
  }
15907
+ function warnUnsupportedTargets(params) {
15908
+ const { config, supportedTargets, featureName } = params;
15909
+ for (const target of config.getTargets()) {
15910
+ if (!supportedTargets.includes(target) && config.getFeatures(target).includes(featureName)) {
15911
+ logger.warn(`Target '${target}' does not support the feature '${featureName}'. Skipping.`);
15912
+ }
15913
+ }
15914
+ }
15908
15915
  async function checkRulesyncDirExists(params) {
15909
15916
  return fileExists((0, import_node_path115.join)(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
15910
15917
  }
@@ -15942,10 +15949,9 @@ async function generateRulesCore(params) {
15942
15949
  let totalCount = 0;
15943
15950
  const allPaths = [];
15944
15951
  let hasDiff = false;
15945
- const toolTargets = (0, import_es_toolkit4.intersection)(
15946
- config.getTargets(),
15947
- RulesProcessor.getToolTargets({ global: config.getGlobal() })
15948
- );
15952
+ const supportedTargets = RulesProcessor.getToolTargets({ global: config.getGlobal() });
15953
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedTargets);
15954
+ warnUnsupportedTargets({ config, supportedTargets, featureName: "rules" });
15949
15955
  for (const baseDir of config.getBaseDirs()) {
15950
15956
  for (const toolTarget of toolTargets) {
15951
15957
  if (!config.getFeatures(toolTarget).includes("rules")) {
@@ -15977,13 +15983,19 @@ async function generateRulesCore(params) {
15977
15983
  }
15978
15984
  async function generateIgnoreCore(params) {
15979
15985
  const { config } = params;
15986
+ const supportedIgnoreTargets = IgnoreProcessor.getToolTargets();
15987
+ warnUnsupportedTargets({
15988
+ config,
15989
+ supportedTargets: supportedIgnoreTargets,
15990
+ featureName: "ignore"
15991
+ });
15980
15992
  if (config.getGlobal()) {
15981
15993
  return { count: 0, paths: [], hasDiff: false };
15982
15994
  }
15983
15995
  let totalCount = 0;
15984
15996
  const allPaths = [];
15985
15997
  let hasDiff = false;
15986
- for (const toolTarget of (0, import_es_toolkit4.intersection)(config.getTargets(), IgnoreProcessor.getToolTargets())) {
15998
+ for (const toolTarget of (0, import_es_toolkit4.intersection)(config.getTargets(), supportedIgnoreTargets)) {
15987
15999
  if (!config.getFeatures(toolTarget).includes("ignore")) {
15988
16000
  continue;
15989
16001
  }
@@ -16027,10 +16039,9 @@ async function generateMcpCore(params) {
16027
16039
  let totalCount = 0;
16028
16040
  const allPaths = [];
16029
16041
  let hasDiff = false;
16030
- const toolTargets = (0, import_es_toolkit4.intersection)(
16031
- config.getTargets(),
16032
- McpProcessor.getToolTargets({ global: config.getGlobal() })
16033
- );
16042
+ const supportedMcpTargets = McpProcessor.getToolTargets({ global: config.getGlobal() });
16043
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedMcpTargets);
16044
+ warnUnsupportedTargets({ config, supportedTargets: supportedMcpTargets, featureName: "mcp" });
16034
16045
  for (const baseDir of config.getBaseDirs()) {
16035
16046
  for (const toolTarget of toolTargets) {
16036
16047
  if (!config.getFeatures(toolTarget).includes("mcp")) {
@@ -16061,13 +16072,16 @@ async function generateCommandsCore(params) {
16061
16072
  let totalCount = 0;
16062
16073
  const allPaths = [];
16063
16074
  let hasDiff = false;
16064
- const toolTargets = (0, import_es_toolkit4.intersection)(
16065
- config.getTargets(),
16066
- CommandsProcessor.getToolTargets({
16067
- global: config.getGlobal(),
16068
- includeSimulated: config.getSimulateCommands()
16069
- })
16070
- );
16075
+ const supportedCommandsTargets = CommandsProcessor.getToolTargets({
16076
+ global: config.getGlobal(),
16077
+ includeSimulated: config.getSimulateCommands()
16078
+ });
16079
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedCommandsTargets);
16080
+ warnUnsupportedTargets({
16081
+ config,
16082
+ supportedTargets: supportedCommandsTargets,
16083
+ featureName: "commands"
16084
+ });
16071
16085
  for (const baseDir of config.getBaseDirs()) {
16072
16086
  for (const toolTarget of toolTargets) {
16073
16087
  if (!config.getFeatures(toolTarget).includes("commands")) {
@@ -16098,13 +16112,16 @@ async function generateSubagentsCore(params) {
16098
16112
  let totalCount = 0;
16099
16113
  const allPaths = [];
16100
16114
  let hasDiff = false;
16101
- const toolTargets = (0, import_es_toolkit4.intersection)(
16102
- config.getTargets(),
16103
- SubagentsProcessor.getToolTargets({
16104
- global: config.getGlobal(),
16105
- includeSimulated: config.getSimulateSubagents()
16106
- })
16107
- );
16115
+ const supportedSubagentsTargets = SubagentsProcessor.getToolTargets({
16116
+ global: config.getGlobal(),
16117
+ includeSimulated: config.getSimulateSubagents()
16118
+ });
16119
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedSubagentsTargets);
16120
+ warnUnsupportedTargets({
16121
+ config,
16122
+ supportedTargets: supportedSubagentsTargets,
16123
+ featureName: "subagents"
16124
+ });
16108
16125
  for (const baseDir of config.getBaseDirs()) {
16109
16126
  for (const toolTarget of toolTargets) {
16110
16127
  if (!config.getFeatures(toolTarget).includes("subagents")) {
@@ -16136,13 +16153,16 @@ async function generateSkillsCore(params) {
16136
16153
  const allPaths = [];
16137
16154
  let hasDiff = false;
16138
16155
  const allSkills = [];
16139
- const toolTargets = (0, import_es_toolkit4.intersection)(
16140
- config.getTargets(),
16141
- SkillsProcessor.getToolTargets({
16142
- global: config.getGlobal(),
16143
- includeSimulated: config.getSimulateSkills()
16144
- })
16145
- );
16156
+ const supportedSkillsTargets = SkillsProcessor.getToolTargets({
16157
+ global: config.getGlobal(),
16158
+ includeSimulated: config.getSimulateSkills()
16159
+ });
16160
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedSkillsTargets);
16161
+ warnUnsupportedTargets({
16162
+ config,
16163
+ supportedTargets: supportedSkillsTargets,
16164
+ featureName: "skills"
16165
+ });
16146
16166
  for (const baseDir of config.getBaseDirs()) {
16147
16167
  for (const toolTarget of toolTargets) {
16148
16168
  if (!config.getFeatures(toolTarget).includes("skills")) {
@@ -16178,10 +16198,9 @@ async function generateHooksCore(params) {
16178
16198
  let totalCount = 0;
16179
16199
  const allPaths = [];
16180
16200
  let hasDiff = false;
16181
- const toolTargets = (0, import_es_toolkit4.intersection)(
16182
- config.getTargets(),
16183
- HooksProcessor.getToolTargets({ global: config.getGlobal() })
16184
- );
16201
+ const supportedHooksTargets = HooksProcessor.getToolTargets({ global: config.getGlobal() });
16202
+ const toolTargets = (0, import_es_toolkit4.intersection)(config.getTargets(), supportedHooksTargets);
16203
+ warnUnsupportedTargets({ config, supportedTargets: supportedHooksTargets, featureName: "hooks" });
16185
16204
  for (const baseDir of config.getBaseDirs()) {
16186
16205
  for (const toolTarget of toolTargets) {
16187
16206
  if (!config.getFeatures(toolTarget).includes("hooks")) {
@@ -16253,6 +16272,7 @@ async function importRulesCore(params) {
16253
16272
  });
16254
16273
  const toolFiles = await rulesProcessor.loadToolFiles();
16255
16274
  if (toolFiles.length === 0) {
16275
+ logger.warn(`No rule files found for ${tool}. Skipping import.`);
16256
16276
  return 0;
16257
16277
  }
16258
16278
  const rulesyncFiles = await rulesProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16280,6 +16300,7 @@ async function importIgnoreCore(params) {
16280
16300
  });
16281
16301
  const toolFiles = await ignoreProcessor.loadToolFiles();
16282
16302
  if (toolFiles.length === 0) {
16303
+ logger.warn(`No ignore files found for ${tool}. Skipping import.`);
16283
16304
  return 0;
16284
16305
  }
16285
16306
  const rulesyncFiles = await ignoreProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16309,6 +16330,7 @@ async function importMcpCore(params) {
16309
16330
  });
16310
16331
  const toolFiles = await mcpProcessor.loadToolFiles();
16311
16332
  if (toolFiles.length === 0) {
16333
+ logger.warn(`No MCP files found for ${tool}. Skipping import.`);
16312
16334
  return 0;
16313
16335
  }
16314
16336
  const rulesyncFiles = await mcpProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16335,6 +16357,7 @@ async function importCommandsCore(params) {
16335
16357
  });
16336
16358
  const toolFiles = await commandsProcessor.loadToolFiles();
16337
16359
  if (toolFiles.length === 0) {
16360
+ logger.warn(`No command files found for ${tool}. Skipping import.`);
16338
16361
  return 0;
16339
16362
  }
16340
16363
  const rulesyncFiles = await commandsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16361,6 +16384,7 @@ async function importSubagentsCore(params) {
16361
16384
  });
16362
16385
  const toolFiles = await subagentsProcessor.loadToolFiles();
16363
16386
  if (toolFiles.length === 0) {
16387
+ logger.warn(`No subagent files found for ${tool}. Skipping import.`);
16364
16388
  return 0;
16365
16389
  }
16366
16390
  const rulesyncFiles = await subagentsProcessor.convertToolFilesToRulesyncFiles(toolFiles);
@@ -16387,6 +16411,7 @@ async function importSkillsCore(params) {
16387
16411
  });
16388
16412
  const toolDirs = await skillsProcessor.loadToolDirs();
16389
16413
  if (toolDirs.length === 0) {
16414
+ logger.warn(`No skill directories found for ${tool}. Skipping import.`);
16390
16415
  return 0;
16391
16416
  }
16392
16417
  const rulesyncDirs = await skillsProcessor.convertToolDirsToRulesyncDirs(toolDirs);
@@ -16418,6 +16443,7 @@ async function importHooksCore(params) {
16418
16443
  });
16419
16444
  const toolFiles = await hooksProcessor.loadToolFiles();
16420
16445
  if (toolFiles.length === 0) {
16446
+ logger.warn(`No hooks files found for ${tool}. Skipping import.`);
16421
16447
  return 0;
16422
16448
  }
16423
16449
  const rulesyncFiles = await hooksProcessor.convertToolFilesToRulesyncFiles(toolFiles);
package/dist/index.d.cts CHANGED
@@ -165,6 +165,7 @@ declare const RulesyncSkillFrontmatterSchemaInternal: z.ZodMiniObject<{
165
165
  }>>>;
166
166
  claudecode: z.ZodMiniOptional<z.ZodMiniObject<{
167
167
  "allowed-tools": z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
168
+ model: z.ZodMiniOptional<z.ZodMiniString<string>>;
168
169
  }, z.core.$loose>>;
169
170
  codexcli: z.ZodMiniOptional<z.ZodMiniObject<{
170
171
  "short-description": z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -184,6 +185,7 @@ type RulesyncSkillFrontmatterInput = {
184
185
  targets?: ("*" | string)[];
185
186
  claudecode?: {
186
187
  "allowed-tools"?: string[];
188
+ model?: string;
187
189
  };
188
190
  codexcli?: {
189
191
  "short-description"?: string;
package/dist/index.d.ts CHANGED
@@ -165,6 +165,7 @@ declare const RulesyncSkillFrontmatterSchemaInternal: z.ZodMiniObject<{
165
165
  }>>>;
166
166
  claudecode: z.ZodMiniOptional<z.ZodMiniObject<{
167
167
  "allowed-tools": z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
168
+ model: z.ZodMiniOptional<z.ZodMiniString<string>>;
168
169
  }, z.core.$loose>>;
169
170
  codexcli: z.ZodMiniOptional<z.ZodMiniObject<{
170
171
  "short-description": z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -184,6 +185,7 @@ type RulesyncSkillFrontmatterInput = {
184
185
  targets?: ("*" | string)[];
185
186
  claudecode?: {
186
187
  "allowed-tools"?: string[];
188
+ model?: string;
187
189
  };
188
190
  codexcli?: {
189
191
  "short-description"?: string;
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  generate,
7
7
  importFromTool,
8
8
  logger
9
- } from "./chunk-T5MWTRJM.js";
9
+ } from "./chunk-WAWBAZPA.js";
10
10
 
11
11
  // src/index.ts
12
12
  async function generate2(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "7.11.0",
3
+ "version": "7.12.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "keywords": [
6
6
  "ai",