rulesync 5.8.0 → 5.9.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.
Files changed (4) hide show
  1. package/README.md +1 -0
  2. package/dist/index.cjs +306 -171
  3. package/dist/index.js +295 -160
  4. package/package.json +11 -11
package/dist/index.js CHANGED
@@ -93,9 +93,6 @@ var Logger = class {
93
93
  };
94
94
  var logger = new Logger();
95
95
 
96
- // src/cli/commands/generate.ts
97
- import { intersection } from "es-toolkit";
98
-
99
96
  // src/config/config-resolver.ts
100
97
  import { parse as parseJsonc } from "jsonc-parser";
101
98
  import { resolve as resolve2 } from "path";
@@ -467,6 +464,10 @@ function getBaseDirsInLightOfGlobal({
467
464
  return resolvedBaseDirs;
468
465
  }
469
466
 
467
+ // src/lib/generate.ts
468
+ import { intersection } from "es-toolkit";
469
+ import { join as join96 } from "path";
470
+
470
471
  // src/constants/rulesync-paths.ts
471
472
  import { join as join2 } from "path";
472
473
  var RULESYNC_CONFIG_RELATIVE_FILE_PATH = "rulesync.jsonc";
@@ -8916,7 +8917,8 @@ import { join as join74 } from "path";
8916
8917
  import { basename as basename22, join as join73 } from "path";
8917
8918
  import { z as z38 } from "zod/mini";
8918
8919
  var RulesyncRuleFrontmatterSchema = z38.object({
8919
- root: z38.optional(z38.optional(z38.boolean())),
8920
+ root: z38.optional(z38.boolean()),
8921
+ localRoot: z38.optional(z38.boolean()),
8920
8922
  targets: z38.optional(RulesyncTargetsSchema),
8921
8923
  description: z38.optional(z38.string()),
8922
8924
  globs: z38.optional(z38.array(z38.string())),
@@ -9024,6 +9026,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
9024
9026
  }
9025
9027
  const validatedFrontmatter = {
9026
9028
  root: result.data.root ?? false,
9029
+ localRoot: result.data.localRoot ?? false,
9027
9030
  targets: result.data.targets ?? ["*"],
9028
9031
  description: result.data.description ?? "",
9029
9032
  globs: result.data.globs ?? [],
@@ -9057,6 +9060,7 @@ var RulesyncRule = class _RulesyncRule extends RulesyncFile {
9057
9060
  }
9058
9061
  const validatedFrontmatter = {
9059
9062
  root: result.data.root ?? false,
9063
+ localRoot: result.data.localRoot ?? false,
9060
9064
  targets: result.data.targets ?? ["*"],
9061
9065
  description: result.data.description ?? "",
9062
9066
  globs: result.data.globs ?? [],
@@ -11699,9 +11703,11 @@ var RulesProcessor = class extends FeatureProcessor {
11699
11703
  const rulesyncRules = rulesyncFiles.filter(
11700
11704
  (file) => file instanceof RulesyncRule
11701
11705
  );
11706
+ const localRootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().localRoot);
11707
+ const nonLocalRootRules = rulesyncRules.filter((rule) => !rule.getFrontmatter().localRoot);
11702
11708
  const factory = this.getFactory(this.toolTarget);
11703
11709
  const { meta } = factory;
11704
- const toolRules = rulesyncRules.map((rulesyncRule) => {
11710
+ const toolRules = nonLocalRootRules.map((rulesyncRule) => {
11705
11711
  if (!factory.class.isTargetedByRulesyncRule(rulesyncRule)) {
11706
11712
  return null;
11707
11713
  }
@@ -11712,6 +11718,12 @@ var RulesProcessor = class extends FeatureProcessor {
11712
11718
  global: this.global
11713
11719
  });
11714
11720
  }).filter((rule) => rule !== null);
11721
+ if (localRootRules.length > 0 && !this.global) {
11722
+ const localRootRule = localRootRules[0];
11723
+ if (localRootRule && factory.class.isTargetedByRulesyncRule(localRootRule)) {
11724
+ this.handleLocalRootRule(toolRules, localRootRule, factory);
11725
+ }
11726
+ }
11715
11727
  const isSimulated = this.simulateCommands || this.simulateSubagents || this.simulateSkills;
11716
11728
  if (isSimulated && meta.createsSeparateConventionsRule && meta.additionalConventions) {
11717
11729
  const conventionsContent = this.generateAdditionalConventionsSectionFromMeta(meta);
@@ -11766,6 +11778,50 @@ var RulesProcessor = class extends FeatureProcessor {
11766
11778
  };
11767
11779
  });
11768
11780
  }
11781
+ /**
11782
+ * Handle localRoot rule generation based on tool target.
11783
+ * - Claude Code: generates `.claude/CLAUDE.local.md`
11784
+ * - Claude Code Legacy: generates `./CLAUDE.local.md`
11785
+ * - Other tools: appends content to the root file with one blank line separator
11786
+ */
11787
+ handleLocalRootRule(toolRules, localRootRule, _factory) {
11788
+ const localRootBody = localRootRule.getBody();
11789
+ if (this.toolTarget === "claudecode") {
11790
+ const paths = ClaudecodeRule.getSettablePaths({ global: this.global });
11791
+ toolRules.push(
11792
+ new ClaudecodeRule({
11793
+ baseDir: this.baseDir,
11794
+ relativeDirPath: paths.root.relativeDirPath,
11795
+ relativeFilePath: "CLAUDE.local.md",
11796
+ frontmatter: {},
11797
+ body: localRootBody,
11798
+ validate: true,
11799
+ root: true
11800
+ // Treat as root so it doesn't have frontmatter
11801
+ })
11802
+ );
11803
+ } else if (this.toolTarget === "claudecode-legacy") {
11804
+ const paths = ClaudecodeLegacyRule.getSettablePaths({ global: this.global });
11805
+ toolRules.push(
11806
+ new ClaudecodeLegacyRule({
11807
+ baseDir: this.baseDir,
11808
+ relativeDirPath: paths.root.relativeDirPath,
11809
+ relativeFilePath: "CLAUDE.local.md",
11810
+ fileContent: localRootBody,
11811
+ validate: true,
11812
+ root: true
11813
+ // Treat as root so it doesn't have frontmatter
11814
+ })
11815
+ );
11816
+ } else {
11817
+ const rootRule = toolRules.find((rule) => rule.isRoot());
11818
+ if (rootRule) {
11819
+ const currentContent = rootRule.getFileContent();
11820
+ const newContent = currentContent + "\n\n" + localRootBody;
11821
+ rootRule.setFileContent(newContent);
11822
+ }
11823
+ }
11824
+ }
11769
11825
  /**
11770
11826
  * Generate reference section based on meta configuration.
11771
11827
  */
@@ -11834,6 +11890,18 @@ var RulesProcessor = class extends FeatureProcessor {
11834
11890
  if (rootRules.length > 1) {
11835
11891
  throw new Error("Multiple root rulesync rules found");
11836
11892
  }
11893
+ if (rootRules.length === 0 && rulesyncRules.length > 0) {
11894
+ logger.warn(
11895
+ `No root rulesync rule file found. Consider adding 'root: true' to one of your rule files in ${RULESYNC_RULES_RELATIVE_DIR_PATH}.`
11896
+ );
11897
+ }
11898
+ const localRootRules = rulesyncRules.filter((rule) => rule.getFrontmatter().localRoot);
11899
+ if (localRootRules.length > 1) {
11900
+ throw new Error("Multiple localRoot rules found. Only one rule can have localRoot: true");
11901
+ }
11902
+ if (localRootRules.length > 0 && rootRules.length === 0) {
11903
+ throw new Error("localRoot: true requires a root: true rule to exist");
11904
+ }
11837
11905
  if (this.global) {
11838
11906
  const nonRootRules = rulesyncRules.filter((rule) => !rule.getFrontmatter().root);
11839
11907
  if (nonRootRules.length > 0) {
@@ -11841,6 +11909,11 @@ var RulesProcessor = class extends FeatureProcessor {
11841
11909
  `${nonRootRules.length} non-root rulesync rules found, but it's in global mode, so ignoring them`
11842
11910
  );
11843
11911
  }
11912
+ if (localRootRules.length > 0) {
11913
+ logger.warn(
11914
+ `${localRootRules.length} localRoot rules found, but localRoot is not supported in global mode, ignoring them`
11915
+ );
11916
+ }
11844
11917
  return rootRules;
11845
11918
  }
11846
11919
  return rulesyncRules;
@@ -11894,6 +11967,29 @@ var RulesProcessor = class extends FeatureProcessor {
11894
11967
  );
11895
11968
  })();
11896
11969
  logger.debug(`Found ${rootToolRules.length} root tool rule files`);
11970
+ const localRootToolRules = await (async () => {
11971
+ if (!forDeletion) {
11972
+ return [];
11973
+ }
11974
+ if (this.toolTarget !== "claudecode" && this.toolTarget !== "claudecode-legacy") {
11975
+ return [];
11976
+ }
11977
+ if (!settablePaths.root) {
11978
+ return [];
11979
+ }
11980
+ const localRootFilePaths = await findFilesByGlobs(
11981
+ join95(this.baseDir, settablePaths.root.relativeDirPath ?? ".", "CLAUDE.local.md")
11982
+ );
11983
+ return localRootFilePaths.map(
11984
+ (filePath) => factory.class.forDeletion({
11985
+ baseDir: this.baseDir,
11986
+ relativeDirPath: settablePaths.root?.relativeDirPath ?? ".",
11987
+ relativeFilePath: basename24(filePath),
11988
+ global: this.global
11989
+ })
11990
+ ).filter((rule) => rule.isDeletable());
11991
+ })();
11992
+ logger.debug(`Found ${localRootToolRules.length} local root tool rule files for deletion`);
11897
11993
  const nonRootToolRules = await (async () => {
11898
11994
  if (!settablePaths.nonRoot) {
11899
11995
  return [];
@@ -11922,7 +12018,7 @@ var RulesProcessor = class extends FeatureProcessor {
11922
12018
  );
11923
12019
  })();
11924
12020
  logger.debug(`Found ${nonRootToolRules.length} non-root tool rule files`);
11925
- return [...rootToolRules, ...nonRootToolRules];
12021
+ return [...rootToolRules, ...localRootToolRules, ...nonRootToolRules];
11926
12022
  } catch (error) {
11927
12023
  logger.error(`Failed to load tool files: ${formatError(error)}`);
11928
12024
  return [];
@@ -12042,51 +12138,34 @@ ${toonContent}`;
12042
12138
  }
12043
12139
  };
12044
12140
 
12045
- // src/cli/commands/generate.ts
12046
- async function generateCommand(options) {
12047
- const config = await ConfigResolver.resolve(options);
12048
- logger.configure({
12049
- verbose: config.getVerbose(),
12050
- silent: config.getSilent()
12051
- });
12052
- logger.info("Generating files...");
12053
- if (!await fileExists(RULESYNC_RELATIVE_DIR_PATH)) {
12054
- logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
12055
- process.exit(1);
12056
- }
12057
- logger.info(`Base directories: ${config.getBaseDirs().join(", ")}`);
12058
- const totalIgnoreOutputs = await generateIgnore(config);
12059
- const totalMcpOutputs = await generateMcp(config);
12060
- const totalCommandOutputs = await generateCommands(config);
12061
- const totalSubagentOutputs = await generateSubagents(config);
12062
- const skillsResult = await generateSkills(config);
12063
- const totalRulesOutputs = await generateRules(config, {
12141
+ // src/lib/generate.ts
12142
+ async function checkRulesyncDirExists(params) {
12143
+ return fileExists(join96(params.baseDir, RULESYNC_RELATIVE_DIR_PATH));
12144
+ }
12145
+ async function generate(params) {
12146
+ const { config } = params;
12147
+ const ignoreCount = await generateIgnoreCore({ config });
12148
+ const mcpCount = await generateMcpCore({ config });
12149
+ const commandsCount = await generateCommandsCore({ config });
12150
+ const subagentsCount = await generateSubagentsCore({ config });
12151
+ const skillsResult = await generateSkillsCore({ config });
12152
+ const rulesCount = await generateRulesCore({ config, skills: skillsResult.skills });
12153
+ return {
12154
+ rulesCount,
12155
+ ignoreCount,
12156
+ mcpCount,
12157
+ commandsCount,
12158
+ subagentsCount,
12159
+ skillsCount: skillsResult.count,
12064
12160
  skills: skillsResult.skills
12065
- });
12066
- const totalGenerated = totalRulesOutputs + totalMcpOutputs + totalCommandOutputs + totalIgnoreOutputs + totalSubagentOutputs + skillsResult.totalOutputs;
12067
- if (totalGenerated === 0) {
12068
- const enabledFeatures = config.getFeatures().join(", ");
12069
- logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
12070
- return;
12071
- }
12072
- if (totalGenerated > 0) {
12073
- const parts = [];
12074
- if (totalRulesOutputs > 0) parts.push(`${totalRulesOutputs} rules`);
12075
- if (totalIgnoreOutputs > 0) parts.push(`${totalIgnoreOutputs} ignore files`);
12076
- if (totalMcpOutputs > 0) parts.push(`${totalMcpOutputs} MCP files`);
12077
- if (totalCommandOutputs > 0) parts.push(`${totalCommandOutputs} commands`);
12078
- if (totalSubagentOutputs > 0) parts.push(`${totalSubagentOutputs} subagents`);
12079
- if (skillsResult.totalOutputs > 0) parts.push(`${skillsResult.totalOutputs} skills`);
12080
- logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
12081
- }
12161
+ };
12082
12162
  }
12083
- async function generateRules(config, options) {
12163
+ async function generateRulesCore(params) {
12164
+ const { config, skills } = params;
12084
12165
  if (!config.getFeatures().includes("rules")) {
12085
- logger.debug("Skipping rule generation (not in --features)");
12086
12166
  return 0;
12087
12167
  }
12088
- let totalRulesOutputs = 0;
12089
- logger.info("Generating rule files...");
12168
+ let totalCount = 0;
12090
12169
  const toolTargets = intersection(
12091
12170
  config.getTargets(),
12092
12171
  RulesProcessor.getToolTargets({ global: config.getGlobal() })
@@ -12100,7 +12179,7 @@ async function generateRules(config, options) {
12100
12179
  simulateCommands: config.getSimulateCommands(),
12101
12180
  simulateSubagents: config.getSimulateSubagents(),
12102
12181
  simulateSkills: config.getSimulateSkills(),
12103
- skills: options?.skills
12182
+ skills
12104
12183
  });
12105
12184
  if (config.getDelete()) {
12106
12185
  const oldToolFiles = await processor.loadToolFiles({ forDeletion: true });
@@ -12109,23 +12188,20 @@ async function generateRules(config, options) {
12109
12188
  const rulesyncFiles = await processor.loadRulesyncFiles();
12110
12189
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
12111
12190
  const writtenCount = await processor.writeAiFiles(toolFiles);
12112
- totalRulesOutputs += writtenCount;
12113
- logger.success(`Generated ${writtenCount} ${toolTarget} rule(s) in ${baseDir}`);
12191
+ totalCount += writtenCount;
12114
12192
  }
12115
12193
  }
12116
- return totalRulesOutputs;
12194
+ return totalCount;
12117
12195
  }
12118
- async function generateIgnore(config) {
12196
+ async function generateIgnoreCore(params) {
12197
+ const { config } = params;
12119
12198
  if (!config.getFeatures().includes("ignore")) {
12120
- logger.debug("Skipping ignore file generation (not in --features)");
12121
12199
  return 0;
12122
12200
  }
12123
12201
  if (config.getGlobal()) {
12124
- logger.debug("Skipping ignore file generation (not supported in global mode)");
12125
12202
  return 0;
12126
12203
  }
12127
- let totalIgnoreOutputs = 0;
12128
- logger.info("Generating ignore files...");
12204
+ let totalCount = 0;
12129
12205
  for (const toolTarget of intersection(config.getTargets(), IgnoreProcessor.getToolTargets())) {
12130
12206
  for (const baseDir of config.getBaseDirs()) {
12131
12207
  try {
@@ -12141,30 +12217,24 @@ async function generateIgnore(config) {
12141
12217
  if (rulesyncFiles.length > 0) {
12142
12218
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
12143
12219
  const writtenCount = await processor.writeAiFiles(toolFiles);
12144
- totalIgnoreOutputs += writtenCount;
12145
- logger.success(`Generated ${writtenCount} ${toolTarget} ignore file(s) in ${baseDir}`);
12220
+ totalCount += writtenCount;
12146
12221
  }
12147
12222
  } catch (error) {
12148
12223
  logger.warn(
12149
- `Failed to generate ${toolTarget} ignore files for ${baseDir}:`,
12150
- error instanceof Error ? error.message : String(error)
12224
+ `Failed to generate ${toolTarget} ignore files for ${baseDir}: ${formatError(error)}`
12151
12225
  );
12152
12226
  continue;
12153
12227
  }
12154
12228
  }
12155
12229
  }
12156
- return totalIgnoreOutputs;
12230
+ return totalCount;
12157
12231
  }
12158
- async function generateMcp(config) {
12232
+ async function generateMcpCore(params) {
12233
+ const { config } = params;
12159
12234
  if (!config.getFeatures().includes("mcp")) {
12160
- logger.debug("Skipping MCP configuration generation (not in --features)");
12161
12235
  return 0;
12162
12236
  }
12163
- let totalMcpOutputs = 0;
12164
- logger.info("Generating MCP files...");
12165
- if (config.getModularMcp()) {
12166
- logger.info("\u2139\uFE0F Modular MCP support is experimental.");
12167
- }
12237
+ let totalCount = 0;
12168
12238
  const toolTargets = intersection(
12169
12239
  config.getTargets(),
12170
12240
  McpProcessor.getToolTargets({ global: config.getGlobal() })
@@ -12184,19 +12254,17 @@ async function generateMcp(config) {
12184
12254
  const rulesyncFiles = await processor.loadRulesyncFiles();
12185
12255
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
12186
12256
  const writtenCount = await processor.writeAiFiles(toolFiles);
12187
- totalMcpOutputs += writtenCount;
12188
- logger.success(`Generated ${writtenCount} ${toolTarget} MCP configuration(s) in ${baseDir}`);
12257
+ totalCount += writtenCount;
12189
12258
  }
12190
12259
  }
12191
- return totalMcpOutputs;
12260
+ return totalCount;
12192
12261
  }
12193
- async function generateCommands(config) {
12262
+ async function generateCommandsCore(params) {
12263
+ const { config } = params;
12194
12264
  if (!config.getFeatures().includes("commands")) {
12195
- logger.debug("Skipping command file generation (not in --features)");
12196
12265
  return 0;
12197
12266
  }
12198
- let totalCommandOutputs = 0;
12199
- logger.info("Generating command files...");
12267
+ let totalCount = 0;
12200
12268
  const toolTargets = intersection(
12201
12269
  config.getTargets(),
12202
12270
  CommandsProcessor.getToolTargets({
@@ -12218,19 +12286,17 @@ async function generateCommands(config) {
12218
12286
  const rulesyncFiles = await processor.loadRulesyncFiles();
12219
12287
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
12220
12288
  const writtenCount = await processor.writeAiFiles(toolFiles);
12221
- totalCommandOutputs += writtenCount;
12222
- logger.success(`Generated ${writtenCount} ${toolTarget} command(s) in ${baseDir}`);
12289
+ totalCount += writtenCount;
12223
12290
  }
12224
12291
  }
12225
- return totalCommandOutputs;
12292
+ return totalCount;
12226
12293
  }
12227
- async function generateSubagents(config) {
12294
+ async function generateSubagentsCore(params) {
12295
+ const { config } = params;
12228
12296
  if (!config.getFeatures().includes("subagents")) {
12229
- logger.debug("Skipping subagent file generation (not in --features)");
12230
12297
  return 0;
12231
12298
  }
12232
- let totalSubagentOutputs = 0;
12233
- logger.info("Generating subagent files...");
12299
+ let totalCount = 0;
12234
12300
  const toolTargets = intersection(
12235
12301
  config.getTargets(),
12236
12302
  SubagentsProcessor.getToolTargets({
@@ -12252,20 +12318,18 @@ async function generateSubagents(config) {
12252
12318
  const rulesyncFiles = await processor.loadRulesyncFiles();
12253
12319
  const toolFiles = await processor.convertRulesyncFilesToToolFiles(rulesyncFiles);
12254
12320
  const writtenCount = await processor.writeAiFiles(toolFiles);
12255
- totalSubagentOutputs += writtenCount;
12256
- logger.success(`Generated ${writtenCount} ${toolTarget} subagent(s) in ${baseDir}`);
12321
+ totalCount += writtenCount;
12257
12322
  }
12258
12323
  }
12259
- return totalSubagentOutputs;
12324
+ return totalCount;
12260
12325
  }
12261
- async function generateSkills(config) {
12326
+ async function generateSkillsCore(params) {
12327
+ const { config } = params;
12262
12328
  if (!config.getFeatures().includes("skills")) {
12263
- logger.debug("Skipping skill generation (not in --features)");
12264
- return { totalOutputs: 0, skills: [] };
12329
+ return { count: 0, skills: [] };
12265
12330
  }
12266
- let totalSkillOutputs = 0;
12331
+ let totalCount = 0;
12267
12332
  const allSkills = [];
12268
- logger.info("Generating skill files...");
12269
12333
  const toolTargets = intersection(
12270
12334
  config.getTargets(),
12271
12335
  SkillsProcessor.getToolTargets({
@@ -12292,15 +12356,84 @@ async function generateSkills(config) {
12292
12356
  }
12293
12357
  const toolDirs = await processor.convertRulesyncDirsToToolDirs(rulesyncDirs);
12294
12358
  const writtenCount = await processor.writeAiDirs(toolDirs);
12295
- totalSkillOutputs += writtenCount;
12296
- logger.success(`Generated ${writtenCount} ${toolTarget} skill(s) in ${baseDir}`);
12359
+ totalCount += writtenCount;
12360
+ }
12361
+ }
12362
+ return { count: totalCount, skills: allSkills };
12363
+ }
12364
+
12365
+ // src/cli/commands/generate.ts
12366
+ async function generateCommand(options) {
12367
+ const config = await ConfigResolver.resolve(options);
12368
+ logger.configure({
12369
+ verbose: config.getVerbose(),
12370
+ silent: config.getSilent()
12371
+ });
12372
+ logger.info("Generating files...");
12373
+ if (!await checkRulesyncDirExists({ baseDir: config.getBaseDirs()[0] ?? process.cwd() })) {
12374
+ logger.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
12375
+ process.exit(1);
12376
+ }
12377
+ logger.info(`Base directories: ${config.getBaseDirs().join(", ")}`);
12378
+ const features = config.getFeatures();
12379
+ if (features.includes("ignore")) {
12380
+ logger.info("Generating ignore files...");
12381
+ }
12382
+ if (features.includes("mcp")) {
12383
+ logger.info("Generating MCP files...");
12384
+ if (config.getModularMcp()) {
12385
+ logger.info("\u2139\uFE0F Modular MCP support is experimental.");
12297
12386
  }
12298
12387
  }
12299
- return { totalOutputs: totalSkillOutputs, skills: allSkills };
12388
+ if (features.includes("commands")) {
12389
+ logger.info("Generating command files...");
12390
+ }
12391
+ if (features.includes("subagents")) {
12392
+ logger.info("Generating subagent files...");
12393
+ }
12394
+ if (features.includes("skills")) {
12395
+ logger.info("Generating skill files...");
12396
+ }
12397
+ if (features.includes("rules")) {
12398
+ logger.info("Generating rule files...");
12399
+ }
12400
+ const result = await generate({ config });
12401
+ if (result.ignoreCount > 0) {
12402
+ logger.success(`Generated ${result.ignoreCount} ignore file(s)`);
12403
+ }
12404
+ if (result.mcpCount > 0) {
12405
+ logger.success(`Generated ${result.mcpCount} MCP configuration(s)`);
12406
+ }
12407
+ if (result.commandsCount > 0) {
12408
+ logger.success(`Generated ${result.commandsCount} command(s)`);
12409
+ }
12410
+ if (result.subagentsCount > 0) {
12411
+ logger.success(`Generated ${result.subagentsCount} subagent(s)`);
12412
+ }
12413
+ if (result.skillsCount > 0) {
12414
+ logger.success(`Generated ${result.skillsCount} skill(s)`);
12415
+ }
12416
+ if (result.rulesCount > 0) {
12417
+ logger.success(`Generated ${result.rulesCount} rule(s)`);
12418
+ }
12419
+ const totalGenerated = result.rulesCount + result.ignoreCount + result.mcpCount + result.commandsCount + result.subagentsCount + result.skillsCount;
12420
+ if (totalGenerated === 0) {
12421
+ const enabledFeatures = features.join(", ");
12422
+ logger.warn(`\u26A0\uFE0F No files generated for enabled features: ${enabledFeatures}`);
12423
+ return;
12424
+ }
12425
+ const parts = [];
12426
+ if (result.rulesCount > 0) parts.push(`${result.rulesCount} rules`);
12427
+ if (result.ignoreCount > 0) parts.push(`${result.ignoreCount} ignore files`);
12428
+ if (result.mcpCount > 0) parts.push(`${result.mcpCount} MCP files`);
12429
+ if (result.commandsCount > 0) parts.push(`${result.commandsCount} commands`);
12430
+ if (result.subagentsCount > 0) parts.push(`${result.subagentsCount} subagents`);
12431
+ if (result.skillsCount > 0) parts.push(`${result.skillsCount} skills`);
12432
+ logger.success(`\u{1F389} All done! Generated ${totalGenerated} file(s) total (${parts.join(" + ")})`);
12300
12433
  }
12301
12434
 
12302
12435
  // src/cli/commands/gitignore.ts
12303
- import { join as join96 } from "path";
12436
+ import { join as join97 } from "path";
12304
12437
  var RULESYNC_HEADER = "# Generated by Rulesync";
12305
12438
  var LEGACY_RULESYNC_HEADER = "# Generated by rulesync - AI tool configuration files";
12306
12439
  var RULESYNC_IGNORE_ENTRIES = [
@@ -12317,7 +12450,9 @@ var RULESYNC_IGNORE_ENTRIES = [
12317
12450
  "**/.augment-guidelines",
12318
12451
  // Claude Code
12319
12452
  "**/CLAUDE.md",
12453
+ "**/CLAUDE.local.md",
12320
12454
  "**/.claude/CLAUDE.md",
12455
+ "**/.claude/CLAUDE.local.md",
12321
12456
  "**/.claude/memories/",
12322
12457
  "**/.claude/rules/",
12323
12458
  "**/.claude/commands/",
@@ -12441,7 +12576,7 @@ var removeExistingRulesyncEntries = (content) => {
12441
12576
  return result;
12442
12577
  };
12443
12578
  var gitignoreCommand = async () => {
12444
- const gitignorePath = join96(process.cwd(), ".gitignore");
12579
+ const gitignorePath = join97(process.cwd(), ".gitignore");
12445
12580
  let gitignoreContent = "";
12446
12581
  if (await fileExists(gitignorePath)) {
12447
12582
  gitignoreContent = await readFileContent(gitignorePath);
@@ -12643,7 +12778,7 @@ async function importSkills(config, tool) {
12643
12778
  }
12644
12779
 
12645
12780
  // src/cli/commands/init.ts
12646
- import { join as join97 } from "path";
12781
+ import { join as join98 } from "path";
12647
12782
  async function initCommand() {
12648
12783
  logger.info("Initializing rulesync...");
12649
12784
  await ensureDir(RULESYNC_RELATIVE_DIR_PATH);
@@ -12821,14 +12956,14 @@ Keep the summary concise and ready to reuse in future tasks.`
12821
12956
  await ensureDir(subagentPaths.relativeDirPath);
12822
12957
  await ensureDir(skillPaths.relativeDirPath);
12823
12958
  await ensureDir(ignorePaths.recommended.relativeDirPath);
12824
- const ruleFilepath = join97(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
12959
+ const ruleFilepath = join98(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
12825
12960
  if (!await fileExists(ruleFilepath)) {
12826
12961
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
12827
12962
  logger.success(`Created ${ruleFilepath}`);
12828
12963
  } else {
12829
12964
  logger.info(`Skipped ${ruleFilepath} (already exists)`);
12830
12965
  }
12831
- const mcpFilepath = join97(
12966
+ const mcpFilepath = join98(
12832
12967
  mcpPaths.recommended.relativeDirPath,
12833
12968
  mcpPaths.recommended.relativeFilePath
12834
12969
  );
@@ -12838,30 +12973,30 @@ Keep the summary concise and ready to reuse in future tasks.`
12838
12973
  } else {
12839
12974
  logger.info(`Skipped ${mcpFilepath} (already exists)`);
12840
12975
  }
12841
- const commandFilepath = join97(commandPaths.relativeDirPath, sampleCommandFile.filename);
12976
+ const commandFilepath = join98(commandPaths.relativeDirPath, sampleCommandFile.filename);
12842
12977
  if (!await fileExists(commandFilepath)) {
12843
12978
  await writeFileContent(commandFilepath, sampleCommandFile.content);
12844
12979
  logger.success(`Created ${commandFilepath}`);
12845
12980
  } else {
12846
12981
  logger.info(`Skipped ${commandFilepath} (already exists)`);
12847
12982
  }
12848
- const subagentFilepath = join97(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
12983
+ const subagentFilepath = join98(subagentPaths.relativeDirPath, sampleSubagentFile.filename);
12849
12984
  if (!await fileExists(subagentFilepath)) {
12850
12985
  await writeFileContent(subagentFilepath, sampleSubagentFile.content);
12851
12986
  logger.success(`Created ${subagentFilepath}`);
12852
12987
  } else {
12853
12988
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
12854
12989
  }
12855
- const skillDirPath = join97(skillPaths.relativeDirPath, sampleSkillFile.dirName);
12990
+ const skillDirPath = join98(skillPaths.relativeDirPath, sampleSkillFile.dirName);
12856
12991
  await ensureDir(skillDirPath);
12857
- const skillFilepath = join97(skillDirPath, SKILL_FILE_NAME);
12992
+ const skillFilepath = join98(skillDirPath, SKILL_FILE_NAME);
12858
12993
  if (!await fileExists(skillFilepath)) {
12859
12994
  await writeFileContent(skillFilepath, sampleSkillFile.content);
12860
12995
  logger.success(`Created ${skillFilepath}`);
12861
12996
  } else {
12862
12997
  logger.info(`Skipped ${skillFilepath} (already exists)`);
12863
12998
  }
12864
- const ignoreFilepath = join97(
12999
+ const ignoreFilepath = join98(
12865
13000
  ignorePaths.recommended.relativeDirPath,
12866
13001
  ignorePaths.recommended.relativeFilePath
12867
13002
  );
@@ -12880,12 +13015,12 @@ import { FastMCP } from "fastmcp";
12880
13015
  import { z as z51 } from "zod/mini";
12881
13016
 
12882
13017
  // src/mcp/commands.ts
12883
- import { basename as basename25, join as join98 } from "path";
13018
+ import { basename as basename25, join as join99 } from "path";
12884
13019
  import { z as z45 } from "zod/mini";
12885
13020
  var maxCommandSizeBytes = 1024 * 1024;
12886
13021
  var maxCommandsCount = 1e3;
12887
13022
  async function listCommands() {
12888
- const commandsDir = join98(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
13023
+ const commandsDir = join99(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
12889
13024
  try {
12890
13025
  const files = await listDirectoryFiles(commandsDir);
12891
13026
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -12897,7 +13032,7 @@ async function listCommands() {
12897
13032
  });
12898
13033
  const frontmatter = command.getFrontmatter();
12899
13034
  return {
12900
- relativePathFromCwd: join98(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
13035
+ relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, file),
12901
13036
  frontmatter
12902
13037
  };
12903
13038
  } catch (error) {
@@ -12923,7 +13058,7 @@ async function getCommand({ relativePathFromCwd }) {
12923
13058
  relativeFilePath: filename
12924
13059
  });
12925
13060
  return {
12926
- relativePathFromCwd: join98(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
13061
+ relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
12927
13062
  frontmatter: command.getFrontmatter(),
12928
13063
  body: command.getBody()
12929
13064
  };
@@ -12952,7 +13087,7 @@ async function putCommand({
12952
13087
  try {
12953
13088
  const existingCommands = await listCommands();
12954
13089
  const isUpdate = existingCommands.some(
12955
- (command2) => command2.relativePathFromCwd === join98(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
13090
+ (command2) => command2.relativePathFromCwd === join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
12956
13091
  );
12957
13092
  if (!isUpdate && existingCommands.length >= maxCommandsCount) {
12958
13093
  throw new Error(`Maximum number of commands (${maxCommandsCount}) reached`);
@@ -12967,11 +13102,11 @@ async function putCommand({
12967
13102
  fileContent,
12968
13103
  validate: true
12969
13104
  });
12970
- const commandsDir = join98(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
13105
+ const commandsDir = join99(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH);
12971
13106
  await ensureDir(commandsDir);
12972
13107
  await writeFileContent(command.getFilePath(), command.getFileContent());
12973
13108
  return {
12974
- relativePathFromCwd: join98(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
13109
+ relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename),
12975
13110
  frontmatter: command.getFrontmatter(),
12976
13111
  body: command.getBody()
12977
13112
  };
@@ -12987,11 +13122,11 @@ async function deleteCommand({ relativePathFromCwd }) {
12987
13122
  intendedRootDir: process.cwd()
12988
13123
  });
12989
13124
  const filename = basename25(relativePathFromCwd);
12990
- const fullPath = join98(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
13125
+ const fullPath = join99(process.cwd(), RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename);
12991
13126
  try {
12992
13127
  await removeFile(fullPath);
12993
13128
  return {
12994
- relativePathFromCwd: join98(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
13129
+ relativePathFromCwd: join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, filename)
12995
13130
  };
12996
13131
  } catch (error) {
12997
13132
  throw new Error(`Failed to delete command file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -13016,7 +13151,7 @@ var commandToolSchemas = {
13016
13151
  var commandTools = {
13017
13152
  listCommands: {
13018
13153
  name: "listCommands",
13019
- description: `List all commands from ${join98(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
13154
+ description: `List all commands from ${join99(RULESYNC_COMMANDS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
13020
13155
  parameters: commandToolSchemas.listCommands,
13021
13156
  execute: async () => {
13022
13157
  const commands = await listCommands();
@@ -13058,11 +13193,11 @@ var commandTools = {
13058
13193
  };
13059
13194
 
13060
13195
  // src/mcp/ignore.ts
13061
- import { join as join99 } from "path";
13196
+ import { join as join100 } from "path";
13062
13197
  import { z as z46 } from "zod/mini";
13063
13198
  var maxIgnoreFileSizeBytes = 100 * 1024;
13064
13199
  async function getIgnoreFile() {
13065
- const ignoreFilePath = join99(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
13200
+ const ignoreFilePath = join100(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
13066
13201
  try {
13067
13202
  const content = await readFileContent(ignoreFilePath);
13068
13203
  return {
@@ -13076,7 +13211,7 @@ async function getIgnoreFile() {
13076
13211
  }
13077
13212
  }
13078
13213
  async function putIgnoreFile({ content }) {
13079
- const ignoreFilePath = join99(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
13214
+ const ignoreFilePath = join100(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
13080
13215
  const contentSizeBytes = Buffer.byteLength(content, "utf8");
13081
13216
  if (contentSizeBytes > maxIgnoreFileSizeBytes) {
13082
13217
  throw new Error(
@@ -13097,8 +13232,8 @@ async function putIgnoreFile({ content }) {
13097
13232
  }
13098
13233
  }
13099
13234
  async function deleteIgnoreFile() {
13100
- const aiignorePath = join99(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
13101
- const legacyIgnorePath = join99(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
13235
+ const aiignorePath = join100(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
13236
+ const legacyIgnorePath = join100(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
13102
13237
  try {
13103
13238
  await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
13104
13239
  return {
@@ -13153,7 +13288,7 @@ var ignoreTools = {
13153
13288
  };
13154
13289
 
13155
13290
  // src/mcp/mcp.ts
13156
- import { join as join100 } from "path";
13291
+ import { join as join101 } from "path";
13157
13292
  import { z as z47 } from "zod/mini";
13158
13293
  var maxMcpSizeBytes = 1024 * 1024;
13159
13294
  async function getMcpFile() {
@@ -13163,7 +13298,7 @@ async function getMcpFile() {
13163
13298
  validate: true,
13164
13299
  modularMcp: config.getModularMcp()
13165
13300
  });
13166
- const relativePathFromCwd = join100(
13301
+ const relativePathFromCwd = join101(
13167
13302
  rulesyncMcp.getRelativeDirPath(),
13168
13303
  rulesyncMcp.getRelativeFilePath()
13169
13304
  );
@@ -13196,7 +13331,7 @@ async function putMcpFile({ content }) {
13196
13331
  const paths = RulesyncMcp.getSettablePaths();
13197
13332
  const relativeDirPath = paths.recommended.relativeDirPath;
13198
13333
  const relativeFilePath = paths.recommended.relativeFilePath;
13199
- const fullPath = join100(baseDir, relativeDirPath, relativeFilePath);
13334
+ const fullPath = join101(baseDir, relativeDirPath, relativeFilePath);
13200
13335
  const rulesyncMcp = new RulesyncMcp({
13201
13336
  baseDir,
13202
13337
  relativeDirPath,
@@ -13205,9 +13340,9 @@ async function putMcpFile({ content }) {
13205
13340
  validate: true,
13206
13341
  modularMcp: config.getModularMcp()
13207
13342
  });
13208
- await ensureDir(join100(baseDir, relativeDirPath));
13343
+ await ensureDir(join101(baseDir, relativeDirPath));
13209
13344
  await writeFileContent(fullPath, content);
13210
- const relativePathFromCwd = join100(relativeDirPath, relativeFilePath);
13345
+ const relativePathFromCwd = join101(relativeDirPath, relativeFilePath);
13211
13346
  return {
13212
13347
  relativePathFromCwd,
13213
13348
  content: rulesyncMcp.getFileContent()
@@ -13222,15 +13357,15 @@ async function deleteMcpFile() {
13222
13357
  try {
13223
13358
  const baseDir = process.cwd();
13224
13359
  const paths = RulesyncMcp.getSettablePaths();
13225
- const recommendedPath = join100(
13360
+ const recommendedPath = join101(
13226
13361
  baseDir,
13227
13362
  paths.recommended.relativeDirPath,
13228
13363
  paths.recommended.relativeFilePath
13229
13364
  );
13230
- const legacyPath = join100(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
13365
+ const legacyPath = join101(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
13231
13366
  await removeFile(recommendedPath);
13232
13367
  await removeFile(legacyPath);
13233
- const relativePathFromCwd = join100(
13368
+ const relativePathFromCwd = join101(
13234
13369
  paths.recommended.relativeDirPath,
13235
13370
  paths.recommended.relativeFilePath
13236
13371
  );
@@ -13281,12 +13416,12 @@ var mcpTools = {
13281
13416
  };
13282
13417
 
13283
13418
  // src/mcp/rules.ts
13284
- import { basename as basename26, join as join101 } from "path";
13419
+ import { basename as basename26, join as join102 } from "path";
13285
13420
  import { z as z48 } from "zod/mini";
13286
13421
  var maxRuleSizeBytes = 1024 * 1024;
13287
13422
  var maxRulesCount = 1e3;
13288
13423
  async function listRules() {
13289
- const rulesDir = join101(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
13424
+ const rulesDir = join102(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
13290
13425
  try {
13291
13426
  const files = await listDirectoryFiles(rulesDir);
13292
13427
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -13299,7 +13434,7 @@ async function listRules() {
13299
13434
  });
13300
13435
  const frontmatter = rule.getFrontmatter();
13301
13436
  return {
13302
- relativePathFromCwd: join101(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
13437
+ relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, file),
13303
13438
  frontmatter
13304
13439
  };
13305
13440
  } catch (error) {
@@ -13326,7 +13461,7 @@ async function getRule({ relativePathFromCwd }) {
13326
13461
  validate: true
13327
13462
  });
13328
13463
  return {
13329
- relativePathFromCwd: join101(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
13464
+ relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
13330
13465
  frontmatter: rule.getFrontmatter(),
13331
13466
  body: rule.getBody()
13332
13467
  };
@@ -13355,7 +13490,7 @@ async function putRule({
13355
13490
  try {
13356
13491
  const existingRules = await listRules();
13357
13492
  const isUpdate = existingRules.some(
13358
- (rule2) => rule2.relativePathFromCwd === join101(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
13493
+ (rule2) => rule2.relativePathFromCwd === join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
13359
13494
  );
13360
13495
  if (!isUpdate && existingRules.length >= maxRulesCount) {
13361
13496
  throw new Error(`Maximum number of rules (${maxRulesCount}) reached`);
@@ -13368,11 +13503,11 @@ async function putRule({
13368
13503
  body,
13369
13504
  validate: true
13370
13505
  });
13371
- const rulesDir = join101(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
13506
+ const rulesDir = join102(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH);
13372
13507
  await ensureDir(rulesDir);
13373
13508
  await writeFileContent(rule.getFilePath(), rule.getFileContent());
13374
13509
  return {
13375
- relativePathFromCwd: join101(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
13510
+ relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename),
13376
13511
  frontmatter: rule.getFrontmatter(),
13377
13512
  body: rule.getBody()
13378
13513
  };
@@ -13388,11 +13523,11 @@ async function deleteRule({ relativePathFromCwd }) {
13388
13523
  intendedRootDir: process.cwd()
13389
13524
  });
13390
13525
  const filename = basename26(relativePathFromCwd);
13391
- const fullPath = join101(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
13526
+ const fullPath = join102(process.cwd(), RULESYNC_RULES_RELATIVE_DIR_PATH, filename);
13392
13527
  try {
13393
13528
  await removeFile(fullPath);
13394
13529
  return {
13395
- relativePathFromCwd: join101(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
13530
+ relativePathFromCwd: join102(RULESYNC_RULES_RELATIVE_DIR_PATH, filename)
13396
13531
  };
13397
13532
  } catch (error) {
13398
13533
  throw new Error(`Failed to delete rule file ${relativePathFromCwd}: ${formatError(error)}`, {
@@ -13417,7 +13552,7 @@ var ruleToolSchemas = {
13417
13552
  var ruleTools = {
13418
13553
  listRules: {
13419
13554
  name: "listRules",
13420
- description: `List all rules from ${join101(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
13555
+ description: `List all rules from ${join102(RULESYNC_RULES_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
13421
13556
  parameters: ruleToolSchemas.listRules,
13422
13557
  execute: async () => {
13423
13558
  const rules = await listRules();
@@ -13459,7 +13594,7 @@ var ruleTools = {
13459
13594
  };
13460
13595
 
13461
13596
  // src/mcp/skills.ts
13462
- import { basename as basename27, dirname as dirname2, join as join102 } from "path";
13597
+ import { basename as basename27, dirname as dirname2, join as join103 } from "path";
13463
13598
  import { z as z49 } from "zod/mini";
13464
13599
  var maxSkillSizeBytes = 1024 * 1024;
13465
13600
  var maxSkillsCount = 1e3;
@@ -13483,9 +13618,9 @@ function extractDirName(relativeDirPathFromCwd) {
13483
13618
  return dirName;
13484
13619
  }
13485
13620
  async function listSkills() {
13486
- const skillsDir = join102(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
13621
+ const skillsDir = join103(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH);
13487
13622
  try {
13488
- const skillDirPaths = await findFilesByGlobs(join102(skillsDir, "*"), { type: "dir" });
13623
+ const skillDirPaths = await findFilesByGlobs(join103(skillsDir, "*"), { type: "dir" });
13489
13624
  const skills = await Promise.all(
13490
13625
  skillDirPaths.map(async (dirPath) => {
13491
13626
  const dirName = basename27(dirPath);
@@ -13496,7 +13631,7 @@ async function listSkills() {
13496
13631
  });
13497
13632
  const frontmatter = skill.getFrontmatter();
13498
13633
  return {
13499
- relativeDirPathFromCwd: join102(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
13634
+ relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
13500
13635
  frontmatter
13501
13636
  };
13502
13637
  } catch (error) {
@@ -13522,7 +13657,7 @@ async function getSkill({ relativeDirPathFromCwd }) {
13522
13657
  dirName
13523
13658
  });
13524
13659
  return {
13525
- relativeDirPathFromCwd: join102(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
13660
+ relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
13526
13661
  frontmatter: skill.getFrontmatter(),
13527
13662
  body: skill.getBody(),
13528
13663
  otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
@@ -13556,7 +13691,7 @@ async function putSkill({
13556
13691
  try {
13557
13692
  const existingSkills = await listSkills();
13558
13693
  const isUpdate = existingSkills.some(
13559
- (skill2) => skill2.relativeDirPathFromCwd === join102(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
13694
+ (skill2) => skill2.relativeDirPathFromCwd === join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
13560
13695
  );
13561
13696
  if (!isUpdate && existingSkills.length >= maxSkillsCount) {
13562
13697
  throw new Error(`Maximum number of skills (${maxSkillsCount}) reached`);
@@ -13571,9 +13706,9 @@ async function putSkill({
13571
13706
  otherFiles: aiDirFiles,
13572
13707
  validate: true
13573
13708
  });
13574
- const skillDirPath = join102(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
13709
+ const skillDirPath = join103(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
13575
13710
  await ensureDir(skillDirPath);
13576
- const skillFilePath = join102(skillDirPath, SKILL_FILE_NAME);
13711
+ const skillFilePath = join103(skillDirPath, SKILL_FILE_NAME);
13577
13712
  const skillFileContent = stringifyFrontmatter(body, frontmatter);
13578
13713
  await writeFileContent(skillFilePath, skillFileContent);
13579
13714
  for (const file of otherFiles) {
@@ -13581,15 +13716,15 @@ async function putSkill({
13581
13716
  relativePath: file.name,
13582
13717
  intendedRootDir: skillDirPath
13583
13718
  });
13584
- const filePath = join102(skillDirPath, file.name);
13585
- const fileDir = join102(skillDirPath, dirname2(file.name));
13719
+ const filePath = join103(skillDirPath, file.name);
13720
+ const fileDir = join103(skillDirPath, dirname2(file.name));
13586
13721
  if (fileDir !== skillDirPath) {
13587
13722
  await ensureDir(fileDir);
13588
13723
  }
13589
13724
  await writeFileContent(filePath, file.body);
13590
13725
  }
13591
13726
  return {
13592
- relativeDirPathFromCwd: join102(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
13727
+ relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName),
13593
13728
  frontmatter: skill.getFrontmatter(),
13594
13729
  body: skill.getBody(),
13595
13730
  otherFiles: skill.getOtherFiles().map(aiDirFileToMcpSkillFile)
@@ -13611,13 +13746,13 @@ async function deleteSkill({
13611
13746
  intendedRootDir: process.cwd()
13612
13747
  });
13613
13748
  const dirName = extractDirName(relativeDirPathFromCwd);
13614
- const skillDirPath = join102(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
13749
+ const skillDirPath = join103(process.cwd(), RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName);
13615
13750
  try {
13616
13751
  if (await directoryExists(skillDirPath)) {
13617
13752
  await removeDirectory(skillDirPath);
13618
13753
  }
13619
13754
  return {
13620
- relativeDirPathFromCwd: join102(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
13755
+ relativeDirPathFromCwd: join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, dirName)
13621
13756
  };
13622
13757
  } catch (error) {
13623
13758
  throw new Error(
@@ -13650,7 +13785,7 @@ var skillToolSchemas = {
13650
13785
  var skillTools = {
13651
13786
  listSkills: {
13652
13787
  name: "listSkills",
13653
- description: `List all skills from ${join102(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
13788
+ description: `List all skills from ${join103(RULESYNC_SKILLS_RELATIVE_DIR_PATH, "*", SKILL_FILE_NAME)} with their frontmatter.`,
13654
13789
  parameters: skillToolSchemas.listSkills,
13655
13790
  execute: async () => {
13656
13791
  const skills = await listSkills();
@@ -13693,12 +13828,12 @@ var skillTools = {
13693
13828
  };
13694
13829
 
13695
13830
  // src/mcp/subagents.ts
13696
- import { basename as basename28, join as join103 } from "path";
13831
+ import { basename as basename28, join as join104 } from "path";
13697
13832
  import { z as z50 } from "zod/mini";
13698
13833
  var maxSubagentSizeBytes = 1024 * 1024;
13699
13834
  var maxSubagentsCount = 1e3;
13700
13835
  async function listSubagents() {
13701
- const subagentsDir = join103(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
13836
+ const subagentsDir = join104(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
13702
13837
  try {
13703
13838
  const files = await listDirectoryFiles(subagentsDir);
13704
13839
  const mdFiles = files.filter((file) => file.endsWith(".md"));
@@ -13711,7 +13846,7 @@ async function listSubagents() {
13711
13846
  });
13712
13847
  const frontmatter = subagent.getFrontmatter();
13713
13848
  return {
13714
- relativePathFromCwd: join103(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
13849
+ relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, file),
13715
13850
  frontmatter
13716
13851
  };
13717
13852
  } catch (error) {
@@ -13740,7 +13875,7 @@ async function getSubagent({ relativePathFromCwd }) {
13740
13875
  validate: true
13741
13876
  });
13742
13877
  return {
13743
- relativePathFromCwd: join103(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
13878
+ relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
13744
13879
  frontmatter: subagent.getFrontmatter(),
13745
13880
  body: subagent.getBody()
13746
13881
  };
@@ -13769,7 +13904,7 @@ async function putSubagent({
13769
13904
  try {
13770
13905
  const existingSubagents = await listSubagents();
13771
13906
  const isUpdate = existingSubagents.some(
13772
- (subagent2) => subagent2.relativePathFromCwd === join103(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
13907
+ (subagent2) => subagent2.relativePathFromCwd === join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
13773
13908
  );
13774
13909
  if (!isUpdate && existingSubagents.length >= maxSubagentsCount) {
13775
13910
  throw new Error(`Maximum number of subagents (${maxSubagentsCount}) reached`);
@@ -13782,11 +13917,11 @@ async function putSubagent({
13782
13917
  body,
13783
13918
  validate: true
13784
13919
  });
13785
- const subagentsDir = join103(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
13920
+ const subagentsDir = join104(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH);
13786
13921
  await ensureDir(subagentsDir);
13787
13922
  await writeFileContent(subagent.getFilePath(), subagent.getFileContent());
13788
13923
  return {
13789
- relativePathFromCwd: join103(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
13924
+ relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename),
13790
13925
  frontmatter: subagent.getFrontmatter(),
13791
13926
  body: subagent.getBody()
13792
13927
  };
@@ -13802,11 +13937,11 @@ async function deleteSubagent({ relativePathFromCwd }) {
13802
13937
  intendedRootDir: process.cwd()
13803
13938
  });
13804
13939
  const filename = basename28(relativePathFromCwd);
13805
- const fullPath = join103(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
13940
+ const fullPath = join104(process.cwd(), RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename);
13806
13941
  try {
13807
13942
  await removeFile(fullPath);
13808
13943
  return {
13809
- relativePathFromCwd: join103(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
13944
+ relativePathFromCwd: join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, filename)
13810
13945
  };
13811
13946
  } catch (error) {
13812
13947
  throw new Error(
@@ -13834,7 +13969,7 @@ var subagentToolSchemas = {
13834
13969
  var subagentTools = {
13835
13970
  listSubagents: {
13836
13971
  name: "listSubagents",
13837
- description: `List all subagents from ${join103(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
13972
+ description: `List all subagents from ${join104(RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH, "*.md")} with their frontmatter.`,
13838
13973
  parameters: subagentToolSchemas.listSubagents,
13839
13974
  execute: async () => {
13840
13975
  const subagents = await listSubagents();
@@ -14085,7 +14220,7 @@ async function mcpCommand({ version }) {
14085
14220
  }
14086
14221
 
14087
14222
  // src/cli/index.ts
14088
- var getVersion = () => "5.8.0";
14223
+ var getVersion = () => "5.9.0";
14089
14224
  var main = async () => {
14090
14225
  const program = new Command();
14091
14226
  const version = getVersion();