rulesync 0.5.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -11,6 +11,7 @@ A Node.js CLI tool that automatically generates configuration files for various
11
11
  - **Cursor Project Rules** (`.cursor/rules/*.mdc`)
12
12
  - **Cline Rules** (`.clinerules/*.md`)
13
13
  - **Claude Code Memory** (`./CLAUDE.md` + `.claude/memories/*.md`)
14
+ - **Roo Code Rules** (`.roo/rules/*.md`)
14
15
 
15
16
  ## Installation
16
17
 
@@ -165,7 +166,7 @@ Define metadata in front matter for each Markdown file:
165
166
  ```markdown
166
167
  ---
167
168
  root: true # or false
168
- targets: ["*"] # or [copilot, cursor, cline, claudecode]
169
+ targets: ["*"] # or [copilot, cursor, cline, claude, roo]
169
170
  description: "TypeScript coding rules"
170
171
  globs: ["**/*.ts", "**/*.tsx"]
171
172
  ---
@@ -197,6 +198,7 @@ Each AI tool handles rule levels differently:
197
198
  | **Cursor** | `ruletype: always` | `ruletype: autoattached` | Detail rules without globs use `ruletype: agentrequested` |
198
199
  | **GitHub Copilot** | Standard format | Standard format | All rules use same format with frontmatter |
199
200
  | **Cline** | Standard format | Standard format | All rules use plain Markdown format |
201
+ | **Roo Code** | Standard format | Standard format | All rules use plain Markdown format with description header |
200
202
 
201
203
  ### 3. Generate Configuration Files
202
204
 
@@ -209,6 +211,7 @@ rulesync generate --copilot
209
211
  rulesync generate --cursor
210
212
  rulesync generate --cline
211
213
  rulesync generate --claude
214
+ rulesync generate --roo
212
215
 
213
216
  # Clean build (delete existing files first)
214
217
  rulesync generate --delete
@@ -225,7 +228,7 @@ rulesync generate --delete --verbose
225
228
 
226
229
  - `--delete`: Remove all existing generated files before creating new ones
227
230
  - `--verbose`: Show detailed output during generation process
228
- - `--copilot`, `--cursor`, `--cline`, `--claude`: Generate only for specified tools
231
+ - `--copilot`, `--cursor`, `--cline`, `--claude`, `--roo`: Generate only for specified tools
229
232
 
230
233
  ### 4. Other Commands
231
234
 
@@ -291,7 +294,7 @@ This project follows TypeScript-first development with clean architecture princi
291
294
  ```markdown
292
295
  ---
293
296
  root: false
294
- targets: ["copilot", "cursor"]
297
+ targets: ["copilot", "cursor", "roo"]
295
298
  description: "TypeScript coding standards"
296
299
  globs: ["**/*.ts", "**/*.tsx"]
297
300
  ---
@@ -311,6 +314,7 @@ globs: ["**/*.ts", "**/*.tsx"]
311
314
  | **Cursor** | `.cursor/rules/*.mdc` | MDC (YAML header + Markdown) | Root: `ruletype: always`<br>Non-root: `ruletype: autoattached`<br>Non-root without globs: `ruletype: agentrequested` |
312
315
  | **Cline** | `.clinerules/*.md` | Plain Markdown | Both levels use same format |
313
316
  | **Claude Code** | `./CLAUDE.md` (root)<br>`.claude/memories/*.md` (non-root) | Plain Markdown | Root goes to CLAUDE.md<br>Non-root go to separate memory files<br>CLAUDE.md includes `@filename` references |
317
+ | **Roo Code** | `.roo/rules/*.md` | Plain Markdown | Both levels use same format with description header |
314
318
 
315
319
  ## Validation
316
320
 
package/dist/index.js CHANGED
@@ -51,8 +51,10 @@ async function generateClaudeConfig(rules, config) {
51
51
  function generateClaudeMarkdown(rootRules, detailRules) {
52
52
  const lines = [];
53
53
  if (detailRules.length > 0) {
54
+ lines.push("Please also reference the following documents as needed:");
55
+ lines.push("");
54
56
  for (const rule of detailRules) {
55
- lines.push(`@${rule.filename}`);
57
+ lines.push(`@.claude/memories/${rule.filename}.md`);
56
58
  }
57
59
  lines.push("");
58
60
  }
@@ -71,38 +73,14 @@ function generateClaudeMarkdown(rootRules, detailRules) {
71
73
  }
72
74
  function formatRuleForClaude(rule) {
73
75
  const lines = [];
74
- lines.push(`### ${rule.filename}`);
76
+ lines.push(`### ${rule.frontmatter.description}`);
75
77
  lines.push("");
76
- if (rule.frontmatter.description) {
77
- lines.push(`**Description:** ${rule.frontmatter.description}`);
78
- lines.push("");
79
- }
80
- if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
81
- lines.push(`**File patterns:** ${rule.frontmatter.globs.join(", ")}`);
82
- lines.push("");
83
- }
84
78
  lines.push(rule.content);
85
79
  lines.push("");
86
80
  return lines;
87
81
  }
88
82
  function generateMemoryFile(rule) {
89
- const lines = [];
90
- lines.push("Please also refer to the following files as needed:");
91
- lines.push("");
92
- lines.push("---");
93
- lines.push("");
94
- lines.push(`# ${rule.filename}`);
95
- lines.push("");
96
- if (rule.frontmatter.description) {
97
- lines.push(`**Description:** ${rule.frontmatter.description}`);
98
- lines.push("");
99
- }
100
- if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
101
- lines.push(`**File patterns:** ${rule.frontmatter.globs.join(", ")}`);
102
- lines.push("");
103
- }
104
- lines.push(rule.content);
105
- return lines.join("\n");
83
+ return rule.content;
106
84
  }
107
85
 
108
86
  // src/generators/cline.ts
@@ -121,15 +99,7 @@ async function generateClineConfig(rules, config) {
121
99
  return outputs;
122
100
  }
123
101
  function generateClineMarkdown(rule) {
124
- const lines = [];
125
- lines.push(`# ${rule.frontmatter.description}`);
126
- lines.push("");
127
- if (rule.frontmatter.globs.length > 0) {
128
- lines.push(`**Applies to files:** ${rule.frontmatter.globs.join(", ")}`);
129
- lines.push("");
130
- }
131
- lines.push(rule.content);
132
- return lines.join("\n");
102
+ return rule.content;
133
103
  }
134
104
 
135
105
  // src/generators/copilot.ts
@@ -158,7 +128,6 @@ function generateCopilotMarkdown(rule) {
158
128
  lines.push('applyTo: "**"');
159
129
  }
160
130
  lines.push("---");
161
- lines.push("");
162
131
  lines.push(rule.content);
163
132
  return lines.join("\n");
164
133
  }
@@ -195,7 +164,27 @@ function generateCursorMarkdown(rule) {
195
164
  }
196
165
  lines.push(`ruletype: ${ruletype}`);
197
166
  lines.push("---");
198
- lines.push("");
167
+ lines.push(rule.content);
168
+ return lines.join("\n");
169
+ }
170
+
171
+ // src/generators/roo.ts
172
+ var import_node_path5 = require("path");
173
+ async function generateRooConfig(rules, config) {
174
+ const outputs = [];
175
+ for (const rule of rules) {
176
+ const content = generateRooMarkdown(rule);
177
+ const filepath = (0, import_node_path5.join)(config.outputPaths.roo, `${rule.filename}.md`);
178
+ outputs.push({
179
+ tool: "roo",
180
+ filepath,
181
+ content
182
+ });
183
+ }
184
+ return outputs;
185
+ }
186
+ function generateRooMarkdown(rule) {
187
+ const lines = [];
199
188
  lines.push(rule.content);
200
189
  return lines.join("\n");
201
190
  }
@@ -208,10 +197,11 @@ function getDefaultConfig() {
208
197
  copilot: ".github/instructions",
209
198
  cursor: ".cursor/rules",
210
199
  cline: ".clinerules",
211
- claude: "."
200
+ claude: ".",
201
+ roo: ".roo/rules"
212
202
  },
213
203
  watchEnabled: false,
214
- defaultTargets: ["copilot", "cursor", "cline", "claude"]
204
+ defaultTargets: ["copilot", "cursor", "cline", "claude", "roo"]
215
205
  };
216
206
  }
217
207
  function resolveTargets(targets, config) {
@@ -223,7 +213,7 @@ function resolveTargets(targets, config) {
223
213
 
224
214
  // src/utils/file.ts
225
215
  var import_promises = require("fs/promises");
226
- var import_node_path5 = require("path");
216
+ var import_node_path6 = require("path");
227
217
  async function ensureDir(dirPath) {
228
218
  try {
229
219
  await (0, import_promises.stat)(dirPath);
@@ -235,13 +225,13 @@ async function readFileContent(filepath) {
235
225
  return (0, import_promises.readFile)(filepath, "utf-8");
236
226
  }
237
227
  async function writeFileContent(filepath, content) {
238
- await ensureDir((0, import_node_path5.dirname)(filepath));
228
+ await ensureDir((0, import_node_path6.dirname)(filepath));
239
229
  await (0, import_promises.writeFile)(filepath, content, "utf-8");
240
230
  }
241
231
  async function findFiles(dir, extension = ".md") {
242
232
  try {
243
233
  const files = await (0, import_promises.readdir)(dir);
244
- return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path5.join)(dir, file));
234
+ return files.filter((file) => file.endsWith(extension)).map((file) => (0, import_node_path6.join)(dir, file));
245
235
  } catch {
246
236
  return [];
247
237
  }
@@ -255,6 +245,11 @@ async function fileExists(filepath) {
255
245
  }
256
246
  }
257
247
  async function removeDirectory(dirPath) {
248
+ const dangerousPaths = [".", "/", "~", "src", "node_modules"];
249
+ if (dangerousPaths.includes(dirPath) || dirPath === "") {
250
+ console.warn(`Skipping deletion of dangerous path: ${dirPath}`);
251
+ return;
252
+ }
258
253
  try {
259
254
  if (await fileExists(dirPath)) {
260
255
  await (0, import_promises.rm)(dirPath, { recursive: true, force: true });
@@ -263,6 +258,25 @@ async function removeDirectory(dirPath) {
263
258
  console.warn(`Failed to remove directory ${dirPath}:`, error);
264
259
  }
265
260
  }
261
+ async function removeFile(filepath) {
262
+ try {
263
+ if (await fileExists(filepath)) {
264
+ await (0, import_promises.rm)(filepath);
265
+ }
266
+ } catch (error) {
267
+ console.warn(`Failed to remove file ${filepath}:`, error);
268
+ }
269
+ }
270
+ async function removeClaudeGeneratedFiles() {
271
+ const filesToRemove = ["CLAUDE.md", ".claude/memories"];
272
+ for (const fileOrDir of filesToRemove) {
273
+ if (fileOrDir.endsWith("/memories")) {
274
+ await removeDirectory(fileOrDir);
275
+ } else {
276
+ await removeFile(fileOrDir);
277
+ }
278
+ }
279
+ }
266
280
 
267
281
  // src/core/generator.ts
268
282
  async function generateConfigurations(rules, config, targetTools) {
@@ -297,6 +311,8 @@ async function generateForTool(tool, rules, config) {
297
311
  return generateClineConfig(rules, config);
298
312
  case "claude":
299
313
  return await generateClaudeConfig(rules, config);
314
+ case "roo":
315
+ return generateRooConfig(rules, config);
300
316
  default:
301
317
  console.warn(`Unknown tool: ${tool}`);
302
318
  return null;
@@ -304,7 +320,7 @@ async function generateForTool(tool, rules, config) {
304
320
  }
305
321
 
306
322
  // src/core/parser.ts
307
- var import_node_path6 = require("path");
323
+ var import_node_path7 = require("path");
308
324
  var import_gray_matter = __toESM(require("gray-matter"));
309
325
  async function parseRulesFromDirectory(aiRulesDir) {
310
326
  const ruleFiles = await findFiles(aiRulesDir);
@@ -324,7 +340,7 @@ async function parseRuleFile(filepath) {
324
340
  const parsed = (0, import_gray_matter.default)(content);
325
341
  validateFrontmatter(parsed.data, filepath);
326
342
  const frontmatter = parsed.data;
327
- const filename = (0, import_node_path6.basename)(filepath, ".md");
343
+ const filename = (0, import_node_path7.basename)(filepath, ".md");
328
344
  return {
329
345
  frontmatter,
330
346
  content: parsed.content,
@@ -452,7 +468,10 @@ async function generateCommand(options = {}) {
452
468
  deleteTasks.push(removeDirectory(config.outputPaths.cline));
453
469
  break;
454
470
  case "claude":
455
- deleteTasks.push(removeDirectory(config.outputPaths.claude));
471
+ deleteTasks.push(removeClaudeGeneratedFiles());
472
+ break;
473
+ case "roo":
474
+ deleteTasks.push(removeDirectory(config.outputPaths.roo));
456
475
  break;
457
476
  }
458
477
  }
@@ -480,15 +499,18 @@ async function generateCommand(options = {}) {
480
499
 
481
500
  // src/cli/commands/gitignore.ts
482
501
  var import_node_fs = require("fs");
483
- var import_node_path7 = require("path");
502
+ var import_node_path8 = require("path");
484
503
  var gitignoreCommand = async () => {
485
- const gitignorePath = (0, import_node_path7.join)(process.cwd(), ".gitignore");
504
+ const gitignorePath = (0, import_node_path8.join)(process.cwd(), ".gitignore");
486
505
  const rulesFilesToIgnore = [
487
506
  "# Generated by rulesync - AI tool configuration files",
507
+ ".github/copilot-instructions.md",
488
508
  ".github/instructions/",
489
509
  ".cursor/rules/",
490
510
  ".clinerules/",
491
- "CLAUDE.md"
511
+ "CLAUDE.md",
512
+ ".claude/memories/",
513
+ ".roo/rules/"
492
514
  ];
493
515
  let gitignoreContent = "";
494
516
  if ((0, import_node_fs.existsSync)(gitignorePath)) {
@@ -519,7 +541,7 @@ ${linesToAdd.join("\n")}
519
541
  };
520
542
 
521
543
  // src/cli/commands/init.ts
522
- var import_node_path8 = require("path");
544
+ var import_node_path9 = require("path");
523
545
  async function initCommand() {
524
546
  const aiRulesDir = ".rulesync";
525
547
  console.log("Initializing rulesync...");
@@ -609,7 +631,7 @@ globs: ["src/**/*.ts"]
609
631
  }
610
632
  ];
611
633
  for (const file of sampleFiles) {
612
- const filepath = (0, import_node_path8.join)(aiRulesDir, file.filename);
634
+ const filepath = (0, import_node_path9.join)(aiRulesDir, file.filename);
613
635
  if (!await fileExists(filepath)) {
614
636
  await writeFileContent(filepath, file.content);
615
637
  console.log(`Created ${filepath}`);
package/dist/index.mjs CHANGED
@@ -28,8 +28,10 @@ async function generateClaudeConfig(rules, config) {
28
28
  function generateClaudeMarkdown(rootRules, detailRules) {
29
29
  const lines = [];
30
30
  if (detailRules.length > 0) {
31
+ lines.push("Please also reference the following documents as needed:");
32
+ lines.push("");
31
33
  for (const rule of detailRules) {
32
- lines.push(`@${rule.filename}`);
34
+ lines.push(`@.claude/memories/${rule.filename}.md`);
33
35
  }
34
36
  lines.push("");
35
37
  }
@@ -48,38 +50,14 @@ function generateClaudeMarkdown(rootRules, detailRules) {
48
50
  }
49
51
  function formatRuleForClaude(rule) {
50
52
  const lines = [];
51
- lines.push(`### ${rule.filename}`);
53
+ lines.push(`### ${rule.frontmatter.description}`);
52
54
  lines.push("");
53
- if (rule.frontmatter.description) {
54
- lines.push(`**Description:** ${rule.frontmatter.description}`);
55
- lines.push("");
56
- }
57
- if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
58
- lines.push(`**File patterns:** ${rule.frontmatter.globs.join(", ")}`);
59
- lines.push("");
60
- }
61
55
  lines.push(rule.content);
62
56
  lines.push("");
63
57
  return lines;
64
58
  }
65
59
  function generateMemoryFile(rule) {
66
- const lines = [];
67
- lines.push("Please also refer to the following files as needed:");
68
- lines.push("");
69
- lines.push("---");
70
- lines.push("");
71
- lines.push(`# ${rule.filename}`);
72
- lines.push("");
73
- if (rule.frontmatter.description) {
74
- lines.push(`**Description:** ${rule.frontmatter.description}`);
75
- lines.push("");
76
- }
77
- if (rule.frontmatter.globs && rule.frontmatter.globs.length > 0) {
78
- lines.push(`**File patterns:** ${rule.frontmatter.globs.join(", ")}`);
79
- lines.push("");
80
- }
81
- lines.push(rule.content);
82
- return lines.join("\n");
60
+ return rule.content;
83
61
  }
84
62
 
85
63
  // src/generators/cline.ts
@@ -98,15 +76,7 @@ async function generateClineConfig(rules, config) {
98
76
  return outputs;
99
77
  }
100
78
  function generateClineMarkdown(rule) {
101
- const lines = [];
102
- lines.push(`# ${rule.frontmatter.description}`);
103
- lines.push("");
104
- if (rule.frontmatter.globs.length > 0) {
105
- lines.push(`**Applies to files:** ${rule.frontmatter.globs.join(", ")}`);
106
- lines.push("");
107
- }
108
- lines.push(rule.content);
109
- return lines.join("\n");
79
+ return rule.content;
110
80
  }
111
81
 
112
82
  // src/generators/copilot.ts
@@ -135,7 +105,6 @@ function generateCopilotMarkdown(rule) {
135
105
  lines.push('applyTo: "**"');
136
106
  }
137
107
  lines.push("---");
138
- lines.push("");
139
108
  lines.push(rule.content);
140
109
  return lines.join("\n");
141
110
  }
@@ -172,7 +141,27 @@ function generateCursorMarkdown(rule) {
172
141
  }
173
142
  lines.push(`ruletype: ${ruletype}`);
174
143
  lines.push("---");
175
- lines.push("");
144
+ lines.push(rule.content);
145
+ return lines.join("\n");
146
+ }
147
+
148
+ // src/generators/roo.ts
149
+ import { join as join5 } from "path";
150
+ async function generateRooConfig(rules, config) {
151
+ const outputs = [];
152
+ for (const rule of rules) {
153
+ const content = generateRooMarkdown(rule);
154
+ const filepath = join5(config.outputPaths.roo, `${rule.filename}.md`);
155
+ outputs.push({
156
+ tool: "roo",
157
+ filepath,
158
+ content
159
+ });
160
+ }
161
+ return outputs;
162
+ }
163
+ function generateRooMarkdown(rule) {
164
+ const lines = [];
176
165
  lines.push(rule.content);
177
166
  return lines.join("\n");
178
167
  }
@@ -185,10 +174,11 @@ function getDefaultConfig() {
185
174
  copilot: ".github/instructions",
186
175
  cursor: ".cursor/rules",
187
176
  cline: ".clinerules",
188
- claude: "."
177
+ claude: ".",
178
+ roo: ".roo/rules"
189
179
  },
190
180
  watchEnabled: false,
191
- defaultTargets: ["copilot", "cursor", "cline", "claude"]
181
+ defaultTargets: ["copilot", "cursor", "cline", "claude", "roo"]
192
182
  };
193
183
  }
194
184
  function resolveTargets(targets, config) {
@@ -200,7 +190,7 @@ function resolveTargets(targets, config) {
200
190
 
201
191
  // src/utils/file.ts
202
192
  import { mkdir, readdir, readFile, rm, stat, writeFile } from "fs/promises";
203
- import { dirname, join as join5 } from "path";
193
+ import { dirname, join as join6 } from "path";
204
194
  async function ensureDir(dirPath) {
205
195
  try {
206
196
  await stat(dirPath);
@@ -218,7 +208,7 @@ async function writeFileContent(filepath, content) {
218
208
  async function findFiles(dir, extension = ".md") {
219
209
  try {
220
210
  const files = await readdir(dir);
221
- return files.filter((file) => file.endsWith(extension)).map((file) => join5(dir, file));
211
+ return files.filter((file) => file.endsWith(extension)).map((file) => join6(dir, file));
222
212
  } catch {
223
213
  return [];
224
214
  }
@@ -232,6 +222,11 @@ async function fileExists(filepath) {
232
222
  }
233
223
  }
234
224
  async function removeDirectory(dirPath) {
225
+ const dangerousPaths = [".", "/", "~", "src", "node_modules"];
226
+ if (dangerousPaths.includes(dirPath) || dirPath === "") {
227
+ console.warn(`Skipping deletion of dangerous path: ${dirPath}`);
228
+ return;
229
+ }
235
230
  try {
236
231
  if (await fileExists(dirPath)) {
237
232
  await rm(dirPath, { recursive: true, force: true });
@@ -240,6 +235,25 @@ async function removeDirectory(dirPath) {
240
235
  console.warn(`Failed to remove directory ${dirPath}:`, error);
241
236
  }
242
237
  }
238
+ async function removeFile(filepath) {
239
+ try {
240
+ if (await fileExists(filepath)) {
241
+ await rm(filepath);
242
+ }
243
+ } catch (error) {
244
+ console.warn(`Failed to remove file ${filepath}:`, error);
245
+ }
246
+ }
247
+ async function removeClaudeGeneratedFiles() {
248
+ const filesToRemove = ["CLAUDE.md", ".claude/memories"];
249
+ for (const fileOrDir of filesToRemove) {
250
+ if (fileOrDir.endsWith("/memories")) {
251
+ await removeDirectory(fileOrDir);
252
+ } else {
253
+ await removeFile(fileOrDir);
254
+ }
255
+ }
256
+ }
243
257
 
244
258
  // src/core/generator.ts
245
259
  async function generateConfigurations(rules, config, targetTools) {
@@ -274,6 +288,8 @@ async function generateForTool(tool, rules, config) {
274
288
  return generateClineConfig(rules, config);
275
289
  case "claude":
276
290
  return await generateClaudeConfig(rules, config);
291
+ case "roo":
292
+ return generateRooConfig(rules, config);
277
293
  default:
278
294
  console.warn(`Unknown tool: ${tool}`);
279
295
  return null;
@@ -429,7 +445,10 @@ async function generateCommand(options = {}) {
429
445
  deleteTasks.push(removeDirectory(config.outputPaths.cline));
430
446
  break;
431
447
  case "claude":
432
- deleteTasks.push(removeDirectory(config.outputPaths.claude));
448
+ deleteTasks.push(removeClaudeGeneratedFiles());
449
+ break;
450
+ case "roo":
451
+ deleteTasks.push(removeDirectory(config.outputPaths.roo));
433
452
  break;
434
453
  }
435
454
  }
@@ -457,15 +476,18 @@ async function generateCommand(options = {}) {
457
476
 
458
477
  // src/cli/commands/gitignore.ts
459
478
  import { existsSync, readFileSync, writeFileSync } from "fs";
460
- import { join as join6 } from "path";
479
+ import { join as join7 } from "path";
461
480
  var gitignoreCommand = async () => {
462
- const gitignorePath = join6(process.cwd(), ".gitignore");
481
+ const gitignorePath = join7(process.cwd(), ".gitignore");
463
482
  const rulesFilesToIgnore = [
464
483
  "# Generated by rulesync - AI tool configuration files",
484
+ ".github/copilot-instructions.md",
465
485
  ".github/instructions/",
466
486
  ".cursor/rules/",
467
487
  ".clinerules/",
468
- "CLAUDE.md"
488
+ "CLAUDE.md",
489
+ ".claude/memories/",
490
+ ".roo/rules/"
469
491
  ];
470
492
  let gitignoreContent = "";
471
493
  if (existsSync(gitignorePath)) {
@@ -496,7 +518,7 @@ ${linesToAdd.join("\n")}
496
518
  };
497
519
 
498
520
  // src/cli/commands/init.ts
499
- import { join as join7 } from "path";
521
+ import { join as join8 } from "path";
500
522
  async function initCommand() {
501
523
  const aiRulesDir = ".rulesync";
502
524
  console.log("Initializing rulesync...");
@@ -586,7 +608,7 @@ globs: ["src/**/*.ts"]
586
608
  }
587
609
  ];
588
610
  for (const file of sampleFiles) {
589
- const filepath = join7(aiRulesDir, file.filename);
611
+ const filepath = join8(aiRulesDir, file.filename);
590
612
  if (!await fileExists(filepath)) {
591
613
  await writeFileContent(filepath, file.content);
592
614
  console.log(`Created ${filepath}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "0.5.0",
3
+ "version": "0.10.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",