rulesync 3.26.0 → 3.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,7 @@
10
10
  [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/dyoshikawa/rulesync)
11
11
  [![Mentioned in Awesome Claude Code](https://awesome.re/mentioned-badge.svg)](https://github.com/hesreallyhim/awesome-claude-code)
12
12
  [![Mentioned in Awesome Gemini CLI](https://awesome.re/mentioned-badge.svg)](https://github.com/Piebald-AI/awesome-gemini-cli)
13
+ <a href="https://flatt.tech/oss/gmo/trampoline" target="_blank"><img src="https://flatt.tech/assets/images/badges/gmo-oss.svg" height="24px"/></a>
13
14
 
14
15
  A Node.js CLI tool that automatically generates configuration files for various AI development tools from unified AI rule files. Features selective generation, comprehensive import/export capabilities, and supports major AI development tools with rules, commands, MCP, ignore files, subagents and skills.
15
16
 
@@ -142,7 +143,7 @@ Rulesync supports both **generation** and **import** for All of the major AI cod
142
143
  | Gemini CLI | ✅ 🌏 | ✅ | ✅ 🌏 | ✅ 🌏 | 🎮 | 🎮 |
143
144
  | GitHub Copilot | ✅ | | ✅ | ✅ | 🎮 | 🎮 |
144
145
  | Cursor | ✅ | ✅ | ✅ | ✅ 🌏 | 🎮 | 🎮 |
145
- | OpenCode | ✅ | | | | | |
146
+ | OpenCode | ✅ | || | | |
146
147
  | Cline | ✅ | ✅ | ✅ | | | |
147
148
  | Roo Code | ✅ | ✅ | ✅ | ✅ | 🎮 | |
148
149
  | Qwen Code | ✅ | ✅ | | | | |
@@ -390,7 +391,21 @@ Example:
390
391
  }
391
392
  ```
392
393
 
393
- ### `.rulesyncignore`
394
+ ### `.rulesync/.aiignore` or `.rulesyncignore`
395
+
396
+ Rulesync supports a single ignore list that can live in either location below:
397
+
398
+ - `.rulesync/.aiignore` (recommended)
399
+ - `.rulesyncignore` (project root)
400
+
401
+ Rules and behavior:
402
+
403
+ - You may use either location.
404
+ - When both exist, Rulesync prefers `.rulesync/.aiignore` (recommended) over `.rulesyncignore` (legacy) when reading.
405
+ - If neither file exists yet, Rulesync defaults to creating `.rulesync/.aiignore`.
406
+
407
+ Notes:
408
+ - Running `rulesync init` will create `.rulesync/.aiignore` if no ignore file is present.
394
409
 
395
410
  Example:
396
411
 
package/dist/index.cjs CHANGED
@@ -499,6 +499,8 @@ var RULESYNC_RULES_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELA
499
499
  var RULESYNC_COMMANDS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "commands");
500
500
  var RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "subagents");
501
501
  var RULESYNC_MCP_RELATIVE_FILE_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
502
+ var RULESYNC_AIIGNORE_FILE_NAME = ".aiignore";
503
+ var RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, ".aiignore");
502
504
  var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
503
505
  var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
504
506
  var RULESYNC_SKILLS_RELATIVE_DIR_PATH = (0, import_node_path3.join)(RULESYNC_RELATIVE_DIR_PATH, "skills");
@@ -1938,18 +1940,48 @@ var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1938
1940
  }
1939
1941
  static getSettablePaths() {
1940
1942
  return {
1941
- relativeDirPath: ".",
1942
- relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH
1943
+ recommended: {
1944
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
1945
+ relativeFilePath: RULESYNC_AIIGNORE_FILE_NAME
1946
+ },
1947
+ legacy: {
1948
+ relativeDirPath: ".",
1949
+ relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH
1950
+ }
1943
1951
  };
1944
1952
  }
1945
1953
  static async fromFile() {
1946
1954
  const baseDir = process.cwd();
1947
- const filePath = (0, import_node_path15.join)(baseDir, this.getSettablePaths().relativeFilePath);
1948
- const fileContent = await readFileContent(filePath);
1955
+ const paths = this.getSettablePaths();
1956
+ const recommendedPath = (0, import_node_path15.join)(
1957
+ baseDir,
1958
+ paths.recommended.relativeDirPath,
1959
+ paths.recommended.relativeFilePath
1960
+ );
1961
+ const legacyPath = (0, import_node_path15.join)(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
1962
+ if (await fileExists(recommendedPath)) {
1963
+ const fileContent2 = await readFileContent(recommendedPath);
1964
+ return new _RulesyncIgnore({
1965
+ baseDir,
1966
+ relativeDirPath: paths.recommended.relativeDirPath,
1967
+ relativeFilePath: paths.recommended.relativeFilePath,
1968
+ fileContent: fileContent2
1969
+ });
1970
+ }
1971
+ if (await fileExists(legacyPath)) {
1972
+ const fileContent2 = await readFileContent(legacyPath);
1973
+ return new _RulesyncIgnore({
1974
+ baseDir,
1975
+ relativeDirPath: paths.legacy.relativeDirPath,
1976
+ relativeFilePath: paths.legacy.relativeFilePath,
1977
+ fileContent: fileContent2
1978
+ });
1979
+ }
1980
+ const fileContent = await readFileContent(recommendedPath);
1949
1981
  return new _RulesyncIgnore({
1950
1982
  baseDir,
1951
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1952
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1983
+ relativeDirPath: paths.recommended.relativeDirPath,
1984
+ relativeFilePath: paths.recommended.relativeFilePath,
1953
1985
  fileContent
1954
1986
  });
1955
1987
  }
@@ -1986,8 +2018,8 @@ var ToolIgnore = class extends ToolFile {
1986
2018
  toRulesyncIgnoreDefault() {
1987
2019
  return new RulesyncIgnore({
1988
2020
  baseDir: ".",
1989
- relativeDirPath: ".",
1990
- relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
2021
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
2022
+ relativeFilePath: RULESYNC_AIIGNORE_FILE_NAME,
1991
2023
  fileContent: this.fileContent
1992
2024
  });
1993
2025
  }
@@ -2131,8 +2163,8 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2131
2163
  const fileContent = rulesyncPatterns.join("\n");
2132
2164
  return new RulesyncIgnore({
2133
2165
  baseDir: this.baseDir,
2134
- relativeDirPath: RulesyncIgnore.getSettablePaths().relativeDirPath,
2135
- relativeFilePath: RulesyncIgnore.getSettablePaths().relativeFilePath,
2166
+ relativeDirPath: RulesyncIgnore.getSettablePaths().recommended.relativeDirPath,
2167
+ relativeFilePath: RulesyncIgnore.getSettablePaths().recommended.relativeFilePath,
2136
2168
  fileContent
2137
2169
  });
2138
2170
  }
@@ -2254,7 +2286,7 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2254
2286
  return new RulesyncIgnore({
2255
2287
  baseDir: ".",
2256
2288
  relativeDirPath: ".",
2257
- relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
2289
+ relativeFilePath: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH,
2258
2290
  fileContent: this.fileContent
2259
2291
  });
2260
2292
  }
@@ -2661,7 +2693,7 @@ var IgnoreProcessor = class extends FeatureProcessor {
2661
2693
  (file) => file instanceof RulesyncIgnore
2662
2694
  );
2663
2695
  if (!rulesyncIgnore) {
2664
- throw new Error(`No ${RULESYNC_IGNORE_RELATIVE_FILE_PATH} found.`);
2696
+ throw new Error(`No ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH} found.`);
2665
2697
  }
2666
2698
  const toolIgnores = await Promise.all(
2667
2699
  [rulesyncIgnore].map(async (rulesyncIgnore2) => {
@@ -4551,7 +4583,8 @@ var DirFeatureProcessor = class {
4551
4583
  const mainFile = aiDir.getMainFile();
4552
4584
  if (mainFile) {
4553
4585
  const mainFilePath = (0, import_node_path44.join)(dirPath, mainFile.name);
4554
- const contentWithNewline = addTrailingNewline(mainFile.body);
4586
+ const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter);
4587
+ const contentWithNewline = addTrailingNewline(content);
4555
4588
  await writeFileContent(mainFilePath, contentWithNewline);
4556
4589
  }
4557
4590
  const otherFiles = aiDir.getOtherFiles();
@@ -8698,7 +8731,6 @@ var gitignoreCommand = async () => {
8698
8731
  // AGENTS.md
8699
8732
  "**/AGENTS.md",
8700
8733
  "**/.agents/",
8701
- "**/.agents/skills/",
8702
8734
  // Amazon Q
8703
8735
  "**/.amazonq/",
8704
8736
  // Augment
@@ -8724,9 +8756,6 @@ var gitignoreCommand = async () => {
8724
8756
  // Cursor
8725
8757
  "**/.cursor/",
8726
8758
  "**/.cursorignore",
8727
- "**/.cursor/mcp.json",
8728
- "**/.cursor/subagents/",
8729
- "**/.cursor/skills/",
8730
8759
  // Gemini
8731
8760
  "**/GEMINI.md",
8732
8761
  "**/.gemini/memories/",
@@ -8762,7 +8791,8 @@ var gitignoreCommand = async () => {
8762
8791
  "**/.warp/",
8763
8792
  "**/WARP.md",
8764
8793
  // Others
8765
- "**/modular-mcp.json"
8794
+ "**/modular-mcp.json",
8795
+ "!.rulesync/.aiignore"
8766
8796
  ];
8767
8797
  let gitignoreContent = "";
8768
8798
  if (await fileExists(gitignorePath)) {
@@ -8977,7 +9007,7 @@ async function initCommand() {
8977
9007
  logger.success("rulesync initialized successfully!");
8978
9008
  logger.info("Next steps:");
8979
9009
  logger.info(
8980
- `1. Edit ${RULESYNC_RELATIVE_DIR_PATH}/**/*.md, ${RULESYNC_MCP_RELATIVE_FILE_PATH} and ${RULESYNC_IGNORE_RELATIVE_FILE_PATH}`
9010
+ `1. Edit ${RULESYNC_RELATIVE_DIR_PATH}/**/*.md, ${RULESYNC_MCP_RELATIVE_FILE_PATH} and ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}`
8981
9011
  );
8982
9012
  logger.info("2. Run 'rulesync generate' to create configuration files");
8983
9013
  }
@@ -9130,7 +9160,7 @@ Attention, again, you are just the planner, so though you can read any files and
9130
9160
  await ensureDir(mcpPaths.recommended.relativeDirPath);
9131
9161
  await ensureDir(commandPaths.relativeDirPath);
9132
9162
  await ensureDir(subagentPaths.relativeDirPath);
9133
- await ensureDir(ignorePaths.relativeDirPath);
9163
+ await ensureDir(ignorePaths.recommended.relativeDirPath);
9134
9164
  const ruleFilepath = (0, import_node_path81.join)(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
9135
9165
  if (!await fileExists(ruleFilepath)) {
9136
9166
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
@@ -9162,7 +9192,10 @@ Attention, again, you are just the planner, so though you can read any files and
9162
9192
  } else {
9163
9193
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
9164
9194
  }
9165
- const ignoreFilepath = (0, import_node_path81.join)(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
9195
+ const ignoreFilepath = (0, import_node_path81.join)(
9196
+ ignorePaths.recommended.relativeDirPath,
9197
+ ignorePaths.recommended.relativeFilePath
9198
+ );
9166
9199
  if (!await fileExists(ignoreFilepath)) {
9167
9200
  await writeFileContent(ignoreFilepath, sampleIgnoreFile.content);
9168
9201
  logger.success(`Created ${ignoreFilepath}`);
@@ -9357,21 +9390,21 @@ var import_node_path83 = require("path");
9357
9390
  var import_mini31 = require("zod/mini");
9358
9391
  var maxIgnoreFileSizeBytes = 100 * 1024;
9359
9392
  async function getIgnoreFile() {
9360
- const ignoreFilePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9393
+ const ignoreFilePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9361
9394
  try {
9362
9395
  const content = await readFileContent(ignoreFilePath);
9363
9396
  return {
9364
- relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
9397
+ relativePathFromCwd: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH,
9365
9398
  content
9366
9399
  };
9367
9400
  } catch (error) {
9368
- throw new Error(`Failed to read .rulesyncignore file: ${formatError(error)}`, {
9401
+ throw new Error(`Failed to read .rulesync/.aiignore file: ${formatError(error)}`, {
9369
9402
  cause: error
9370
9403
  });
9371
9404
  }
9372
9405
  }
9373
9406
  async function putIgnoreFile({ content }) {
9374
- const ignoreFilePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9407
+ const ignoreFilePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9375
9408
  const contentSizeBytes = Buffer.byteLength(content, "utf8");
9376
9409
  if (contentSizeBytes > maxIgnoreFileSizeBytes) {
9377
9410
  throw new Error(
@@ -9382,26 +9415,32 @@ async function putIgnoreFile({ content }) {
9382
9415
  await ensureDir(process.cwd());
9383
9416
  await writeFileContent(ignoreFilePath, content);
9384
9417
  return {
9385
- relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
9418
+ relativePathFromCwd: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH,
9386
9419
  content
9387
9420
  };
9388
9421
  } catch (error) {
9389
- throw new Error(`Failed to write .rulesyncignore file: ${formatError(error)}`, {
9422
+ throw new Error(`Failed to write .rulesync/.aiignore file: ${formatError(error)}`, {
9390
9423
  cause: error
9391
9424
  });
9392
9425
  }
9393
9426
  }
9394
9427
  async function deleteIgnoreFile() {
9395
- const ignoreFilePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9428
+ const aiignorePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9429
+ const legacyIgnorePath = (0, import_node_path83.join)(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9396
9430
  try {
9397
- await removeFile(ignoreFilePath);
9431
+ await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
9398
9432
  return {
9399
- relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH
9433
+ // Keep the historical return shape — point to the recommended file path
9434
+ // for backward compatibility.
9435
+ relativePathFromCwd: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH
9400
9436
  };
9401
9437
  } catch (error) {
9402
- throw new Error(`Failed to delete .rulesyncignore file: ${formatError(error)}`, {
9403
- cause: error
9404
- });
9438
+ throw new Error(
9439
+ `Failed to delete .rulesyncignore and .rulesync/.aiignore files: ${formatError(error)}`,
9440
+ {
9441
+ cause: error
9442
+ }
9443
+ );
9405
9444
  }
9406
9445
  }
9407
9446
  var ignoreToolSchemas = {
@@ -9423,7 +9462,7 @@ var ignoreTools = {
9423
9462
  },
9424
9463
  putIgnoreFile: {
9425
9464
  name: "putIgnoreFile",
9426
- description: "Create or update the .rulesyncignore file (upsert operation). content parameter is required.",
9465
+ description: "Create or update the .rulesync/.aiignore file (upsert operation). content parameter is required.",
9427
9466
  parameters: ignoreToolSchemas.putIgnoreFile,
9428
9467
  execute: async (args) => {
9429
9468
  const result = await putIgnoreFile({ content: args.content });
@@ -9432,7 +9471,7 @@ var ignoreTools = {
9432
9471
  },
9433
9472
  deleteIgnoreFile: {
9434
9473
  name: "deleteIgnoreFile",
9435
- description: "Delete the .rulesyncignore file from the project root.",
9474
+ description: "Delete the .rulesyncignore and .rulesync/.aiignore files.",
9436
9475
  parameters: ignoreToolSchemas.deleteIgnoreFile,
9437
9476
  execute: async () => {
9438
9477
  const result = await deleteIgnoreFile();
@@ -9963,7 +10002,7 @@ async function mcpCommand({ version }) {
9963
10002
  }
9964
10003
 
9965
10004
  // src/cli/index.ts
9966
- var getVersion = () => "3.26.0";
10005
+ var getVersion = () => "3.27.1";
9967
10006
  var main = async () => {
9968
10007
  const program = new import_commander.Command();
9969
10008
  const version = getVersion();
package/dist/index.js CHANGED
@@ -476,6 +476,8 @@ var RULESYNC_RULES_RELATIVE_DIR_PATH = join2(RULESYNC_RELATIVE_DIR_PATH, "rules"
476
476
  var RULESYNC_COMMANDS_RELATIVE_DIR_PATH = join2(RULESYNC_RELATIVE_DIR_PATH, "commands");
477
477
  var RULESYNC_SUBAGENTS_RELATIVE_DIR_PATH = join2(RULESYNC_RELATIVE_DIR_PATH, "subagents");
478
478
  var RULESYNC_MCP_RELATIVE_FILE_PATH = join2(RULESYNC_RELATIVE_DIR_PATH, "mcp.json");
479
+ var RULESYNC_AIIGNORE_FILE_NAME = ".aiignore";
480
+ var RULESYNC_AIIGNORE_RELATIVE_FILE_PATH = join2(RULESYNC_RELATIVE_DIR_PATH, ".aiignore");
479
481
  var RULESYNC_IGNORE_RELATIVE_FILE_PATH = ".rulesyncignore";
480
482
  var RULESYNC_OVERVIEW_FILE_NAME = "overview.md";
481
483
  var RULESYNC_SKILLS_RELATIVE_DIR_PATH = join2(RULESYNC_RELATIVE_DIR_PATH, "skills");
@@ -1915,18 +1917,48 @@ var RulesyncIgnore = class _RulesyncIgnore extends RulesyncFile {
1915
1917
  }
1916
1918
  static getSettablePaths() {
1917
1919
  return {
1918
- relativeDirPath: ".",
1919
- relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH
1920
+ recommended: {
1921
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
1922
+ relativeFilePath: RULESYNC_AIIGNORE_FILE_NAME
1923
+ },
1924
+ legacy: {
1925
+ relativeDirPath: ".",
1926
+ relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH
1927
+ }
1920
1928
  };
1921
1929
  }
1922
1930
  static async fromFile() {
1923
1931
  const baseDir = process.cwd();
1924
- const filePath = join13(baseDir, this.getSettablePaths().relativeFilePath);
1925
- const fileContent = await readFileContent(filePath);
1932
+ const paths = this.getSettablePaths();
1933
+ const recommendedPath = join13(
1934
+ baseDir,
1935
+ paths.recommended.relativeDirPath,
1936
+ paths.recommended.relativeFilePath
1937
+ );
1938
+ const legacyPath = join13(baseDir, paths.legacy.relativeDirPath, paths.legacy.relativeFilePath);
1939
+ if (await fileExists(recommendedPath)) {
1940
+ const fileContent2 = await readFileContent(recommendedPath);
1941
+ return new _RulesyncIgnore({
1942
+ baseDir,
1943
+ relativeDirPath: paths.recommended.relativeDirPath,
1944
+ relativeFilePath: paths.recommended.relativeFilePath,
1945
+ fileContent: fileContent2
1946
+ });
1947
+ }
1948
+ if (await fileExists(legacyPath)) {
1949
+ const fileContent2 = await readFileContent(legacyPath);
1950
+ return new _RulesyncIgnore({
1951
+ baseDir,
1952
+ relativeDirPath: paths.legacy.relativeDirPath,
1953
+ relativeFilePath: paths.legacy.relativeFilePath,
1954
+ fileContent: fileContent2
1955
+ });
1956
+ }
1957
+ const fileContent = await readFileContent(recommendedPath);
1926
1958
  return new _RulesyncIgnore({
1927
1959
  baseDir,
1928
- relativeDirPath: this.getSettablePaths().relativeDirPath,
1929
- relativeFilePath: this.getSettablePaths().relativeFilePath,
1960
+ relativeDirPath: paths.recommended.relativeDirPath,
1961
+ relativeFilePath: paths.recommended.relativeFilePath,
1930
1962
  fileContent
1931
1963
  });
1932
1964
  }
@@ -1963,8 +1995,8 @@ var ToolIgnore = class extends ToolFile {
1963
1995
  toRulesyncIgnoreDefault() {
1964
1996
  return new RulesyncIgnore({
1965
1997
  baseDir: ".",
1966
- relativeDirPath: ".",
1967
- relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
1998
+ relativeDirPath: RULESYNC_RELATIVE_DIR_PATH,
1999
+ relativeFilePath: RULESYNC_AIIGNORE_FILE_NAME,
1968
2000
  fileContent: this.fileContent
1969
2001
  });
1970
2002
  }
@@ -2108,8 +2140,8 @@ var ClaudecodeIgnore = class _ClaudecodeIgnore extends ToolIgnore {
2108
2140
  const fileContent = rulesyncPatterns.join("\n");
2109
2141
  return new RulesyncIgnore({
2110
2142
  baseDir: this.baseDir,
2111
- relativeDirPath: RulesyncIgnore.getSettablePaths().relativeDirPath,
2112
- relativeFilePath: RulesyncIgnore.getSettablePaths().relativeFilePath,
2143
+ relativeDirPath: RulesyncIgnore.getSettablePaths().recommended.relativeDirPath,
2144
+ relativeFilePath: RulesyncIgnore.getSettablePaths().recommended.relativeFilePath,
2113
2145
  fileContent
2114
2146
  });
2115
2147
  }
@@ -2231,7 +2263,7 @@ var CursorIgnore = class _CursorIgnore extends ToolIgnore {
2231
2263
  return new RulesyncIgnore({
2232
2264
  baseDir: ".",
2233
2265
  relativeDirPath: ".",
2234
- relativeFilePath: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
2266
+ relativeFilePath: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH,
2235
2267
  fileContent: this.fileContent
2236
2268
  });
2237
2269
  }
@@ -2638,7 +2670,7 @@ var IgnoreProcessor = class extends FeatureProcessor {
2638
2670
  (file) => file instanceof RulesyncIgnore
2639
2671
  );
2640
2672
  if (!rulesyncIgnore) {
2641
- throw new Error(`No ${RULESYNC_IGNORE_RELATIVE_FILE_PATH} found.`);
2673
+ throw new Error(`No ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH} found.`);
2642
2674
  }
2643
2675
  const toolIgnores = await Promise.all(
2644
2676
  [rulesyncIgnore].map(async (rulesyncIgnore2) => {
@@ -4528,7 +4560,8 @@ var DirFeatureProcessor = class {
4528
4560
  const mainFile = aiDir.getMainFile();
4529
4561
  if (mainFile) {
4530
4562
  const mainFilePath = join42(dirPath, mainFile.name);
4531
- const contentWithNewline = addTrailingNewline(mainFile.body);
4563
+ const content = stringifyFrontmatter(mainFile.body, mainFile.frontmatter);
4564
+ const contentWithNewline = addTrailingNewline(content);
4532
4565
  await writeFileContent(mainFilePath, contentWithNewline);
4533
4566
  }
4534
4567
  const otherFiles = aiDir.getOtherFiles();
@@ -8675,7 +8708,6 @@ var gitignoreCommand = async () => {
8675
8708
  // AGENTS.md
8676
8709
  "**/AGENTS.md",
8677
8710
  "**/.agents/",
8678
- "**/.agents/skills/",
8679
8711
  // Amazon Q
8680
8712
  "**/.amazonq/",
8681
8713
  // Augment
@@ -8701,9 +8733,6 @@ var gitignoreCommand = async () => {
8701
8733
  // Cursor
8702
8734
  "**/.cursor/",
8703
8735
  "**/.cursorignore",
8704
- "**/.cursor/mcp.json",
8705
- "**/.cursor/subagents/",
8706
- "**/.cursor/skills/",
8707
8736
  // Gemini
8708
8737
  "**/GEMINI.md",
8709
8738
  "**/.gemini/memories/",
@@ -8739,7 +8768,8 @@ var gitignoreCommand = async () => {
8739
8768
  "**/.warp/",
8740
8769
  "**/WARP.md",
8741
8770
  // Others
8742
- "**/modular-mcp.json"
8771
+ "**/modular-mcp.json",
8772
+ "!.rulesync/.aiignore"
8743
8773
  ];
8744
8774
  let gitignoreContent = "";
8745
8775
  if (await fileExists(gitignorePath)) {
@@ -8954,7 +8984,7 @@ async function initCommand() {
8954
8984
  logger.success("rulesync initialized successfully!");
8955
8985
  logger.info("Next steps:");
8956
8986
  logger.info(
8957
- `1. Edit ${RULESYNC_RELATIVE_DIR_PATH}/**/*.md, ${RULESYNC_MCP_RELATIVE_FILE_PATH} and ${RULESYNC_IGNORE_RELATIVE_FILE_PATH}`
8987
+ `1. Edit ${RULESYNC_RELATIVE_DIR_PATH}/**/*.md, ${RULESYNC_MCP_RELATIVE_FILE_PATH} and ${RULESYNC_AIIGNORE_RELATIVE_FILE_PATH}`
8958
8988
  );
8959
8989
  logger.info("2. Run 'rulesync generate' to create configuration files");
8960
8990
  }
@@ -9107,7 +9137,7 @@ Attention, again, you are just the planner, so though you can read any files and
9107
9137
  await ensureDir(mcpPaths.recommended.relativeDirPath);
9108
9138
  await ensureDir(commandPaths.relativeDirPath);
9109
9139
  await ensureDir(subagentPaths.relativeDirPath);
9110
- await ensureDir(ignorePaths.relativeDirPath);
9140
+ await ensureDir(ignorePaths.recommended.relativeDirPath);
9111
9141
  const ruleFilepath = join79(rulePaths.recommended.relativeDirPath, sampleRuleFile.filename);
9112
9142
  if (!await fileExists(ruleFilepath)) {
9113
9143
  await writeFileContent(ruleFilepath, sampleRuleFile.content);
@@ -9139,7 +9169,10 @@ Attention, again, you are just the planner, so though you can read any files and
9139
9169
  } else {
9140
9170
  logger.info(`Skipped ${subagentFilepath} (already exists)`);
9141
9171
  }
9142
- const ignoreFilepath = join79(ignorePaths.relativeDirPath, ignorePaths.relativeFilePath);
9172
+ const ignoreFilepath = join79(
9173
+ ignorePaths.recommended.relativeDirPath,
9174
+ ignorePaths.recommended.relativeFilePath
9175
+ );
9143
9176
  if (!await fileExists(ignoreFilepath)) {
9144
9177
  await writeFileContent(ignoreFilepath, sampleIgnoreFile.content);
9145
9178
  logger.success(`Created ${ignoreFilepath}`);
@@ -9334,21 +9367,21 @@ import { join as join81 } from "path";
9334
9367
  import { z as z31 } from "zod/mini";
9335
9368
  var maxIgnoreFileSizeBytes = 100 * 1024;
9336
9369
  async function getIgnoreFile() {
9337
- const ignoreFilePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9370
+ const ignoreFilePath = join81(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9338
9371
  try {
9339
9372
  const content = await readFileContent(ignoreFilePath);
9340
9373
  return {
9341
- relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
9374
+ relativePathFromCwd: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH,
9342
9375
  content
9343
9376
  };
9344
9377
  } catch (error) {
9345
- throw new Error(`Failed to read .rulesyncignore file: ${formatError(error)}`, {
9378
+ throw new Error(`Failed to read .rulesync/.aiignore file: ${formatError(error)}`, {
9346
9379
  cause: error
9347
9380
  });
9348
9381
  }
9349
9382
  }
9350
9383
  async function putIgnoreFile({ content }) {
9351
- const ignoreFilePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9384
+ const ignoreFilePath = join81(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9352
9385
  const contentSizeBytes = Buffer.byteLength(content, "utf8");
9353
9386
  if (contentSizeBytes > maxIgnoreFileSizeBytes) {
9354
9387
  throw new Error(
@@ -9359,26 +9392,32 @@ async function putIgnoreFile({ content }) {
9359
9392
  await ensureDir(process.cwd());
9360
9393
  await writeFileContent(ignoreFilePath, content);
9361
9394
  return {
9362
- relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH,
9395
+ relativePathFromCwd: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH,
9363
9396
  content
9364
9397
  };
9365
9398
  } catch (error) {
9366
- throw new Error(`Failed to write .rulesyncignore file: ${formatError(error)}`, {
9399
+ throw new Error(`Failed to write .rulesync/.aiignore file: ${formatError(error)}`, {
9367
9400
  cause: error
9368
9401
  });
9369
9402
  }
9370
9403
  }
9371
9404
  async function deleteIgnoreFile() {
9372
- const ignoreFilePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9405
+ const aiignorePath = join81(process.cwd(), RULESYNC_AIIGNORE_RELATIVE_FILE_PATH);
9406
+ const legacyIgnorePath = join81(process.cwd(), RULESYNC_IGNORE_RELATIVE_FILE_PATH);
9373
9407
  try {
9374
- await removeFile(ignoreFilePath);
9408
+ await Promise.all([removeFile(aiignorePath), removeFile(legacyIgnorePath)]);
9375
9409
  return {
9376
- relativePathFromCwd: RULESYNC_IGNORE_RELATIVE_FILE_PATH
9410
+ // Keep the historical return shape — point to the recommended file path
9411
+ // for backward compatibility.
9412
+ relativePathFromCwd: RULESYNC_AIIGNORE_RELATIVE_FILE_PATH
9377
9413
  };
9378
9414
  } catch (error) {
9379
- throw new Error(`Failed to delete .rulesyncignore file: ${formatError(error)}`, {
9380
- cause: error
9381
- });
9415
+ throw new Error(
9416
+ `Failed to delete .rulesyncignore and .rulesync/.aiignore files: ${formatError(error)}`,
9417
+ {
9418
+ cause: error
9419
+ }
9420
+ );
9382
9421
  }
9383
9422
  }
9384
9423
  var ignoreToolSchemas = {
@@ -9400,7 +9439,7 @@ var ignoreTools = {
9400
9439
  },
9401
9440
  putIgnoreFile: {
9402
9441
  name: "putIgnoreFile",
9403
- description: "Create or update the .rulesyncignore file (upsert operation). content parameter is required.",
9442
+ description: "Create or update the .rulesync/.aiignore file (upsert operation). content parameter is required.",
9404
9443
  parameters: ignoreToolSchemas.putIgnoreFile,
9405
9444
  execute: async (args) => {
9406
9445
  const result = await putIgnoreFile({ content: args.content });
@@ -9409,7 +9448,7 @@ var ignoreTools = {
9409
9448
  },
9410
9449
  deleteIgnoreFile: {
9411
9450
  name: "deleteIgnoreFile",
9412
- description: "Delete the .rulesyncignore file from the project root.",
9451
+ description: "Delete the .rulesyncignore and .rulesync/.aiignore files.",
9413
9452
  parameters: ignoreToolSchemas.deleteIgnoreFile,
9414
9453
  execute: async () => {
9415
9454
  const result = await deleteIgnoreFile();
@@ -9940,7 +9979,7 @@ async function mcpCommand({ version }) {
9940
9979
  }
9941
9980
 
9942
9981
  // src/cli/index.ts
9943
- var getVersion = () => "3.26.0";
9982
+ var getVersion = () => "3.27.1";
9944
9983
  var main = async () => {
9945
9984
  const program = new Command();
9946
9985
  const version = getVersion();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "3.26.0",
3
+ "version": "3.27.1",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "keywords": [
6
6
  "ai",