rulesync 0.14.0 → 0.16.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.ja.md +6 -0
- package/README.md +6 -0
- package/dist/index.js +63 -28
- package/dist/index.mjs +63 -28
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -166,6 +166,11 @@ npx rulesync generate --copilot --cursor --delete
|
|
|
166
166
|
# 詳細出力
|
|
167
167
|
npx rulesync generate --verbose
|
|
168
168
|
npx rulesync generate --delete --verbose
|
|
169
|
+
|
|
170
|
+
# 特定のベースディレクトリに生成(monorepoサポート)
|
|
171
|
+
npx rulesync generate --base-dir ./packages/frontend
|
|
172
|
+
npx rulesync generate --base-dir ./packages/frontend,./packages/backend
|
|
173
|
+
npx rulesync generate --base-dir ./apps/web,./apps/api,./packages/shared
|
|
169
174
|
```
|
|
170
175
|
|
|
171
176
|
#### 生成オプション
|
|
@@ -173,6 +178,7 @@ npx rulesync generate --delete --verbose
|
|
|
173
178
|
- `--delete`: 新しいファイルを作成する前に既存の生成済みファイルをすべて削除
|
|
174
179
|
- `--verbose`: 生成プロセス中に詳細出力を表示
|
|
175
180
|
- `--copilot`, `--cursor`, `--cline`, `--claude`, `--roo`: 指定されたツールのみ生成
|
|
181
|
+
- `--base-dir <paths>`: 指定されたベースディレクトリに設定ファイルを生成(複数パスの場合はカンマ区切り)。異なるプロジェクトディレクトリにツール固有の設定を生成したいmonorepoセットアップに便利。
|
|
176
182
|
|
|
177
183
|
### 4. その他のコマンド
|
|
178
184
|
|
package/README.md
CHANGED
|
@@ -166,6 +166,11 @@ npx rulesync generate --copilot --cursor --delete
|
|
|
166
166
|
# Verbose output
|
|
167
167
|
npx rulesync generate --verbose
|
|
168
168
|
npx rulesync generate --delete --verbose
|
|
169
|
+
|
|
170
|
+
# Generate in specific base directories (monorepo support)
|
|
171
|
+
npx rulesync generate --base-dir ./packages/frontend
|
|
172
|
+
npx rulesync generate --base-dir ./packages/frontend,./packages/backend
|
|
173
|
+
npx rulesync generate --base-dir ./apps/web,./apps/api,./packages/shared
|
|
169
174
|
```
|
|
170
175
|
|
|
171
176
|
#### Generate Options
|
|
@@ -173,6 +178,7 @@ npx rulesync generate --delete --verbose
|
|
|
173
178
|
- `--delete`: Remove all existing generated files before creating new ones
|
|
174
179
|
- `--verbose`: Show detailed output during generation process
|
|
175
180
|
- `--copilot`, `--cursor`, `--cline`, `--claude`, `--roo`: Generate only for specified tools
|
|
181
|
+
- `--base-dir <paths>`: Generate configuration files in specified base directories (comma-separated for multiple paths). Useful for monorepo setups where you want to generate tool-specific configurations in different project directories.
|
|
176
182
|
|
|
177
183
|
### 4. Other Commands
|
|
178
184
|
|
package/dist/index.js
CHANGED
|
@@ -90,21 +90,22 @@ async function addCommand(filename) {
|
|
|
90
90
|
|
|
91
91
|
// src/generators/claude.ts
|
|
92
92
|
var import_node_path2 = require("path");
|
|
93
|
-
async function generateClaudeConfig(rules, config) {
|
|
93
|
+
async function generateClaudeConfig(rules, config, baseDir) {
|
|
94
94
|
const outputs = [];
|
|
95
95
|
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
96
96
|
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
97
97
|
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
98
|
+
const claudeOutputDir = baseDir ? (0, import_node_path2.join)(baseDir, config.outputPaths.claude) : config.outputPaths.claude;
|
|
98
99
|
outputs.push({
|
|
99
100
|
tool: "claude",
|
|
100
|
-
filepath: (0, import_node_path2.join)(
|
|
101
|
+
filepath: (0, import_node_path2.join)(claudeOutputDir, "CLAUDE.md"),
|
|
101
102
|
content: claudeMdContent
|
|
102
103
|
});
|
|
103
104
|
for (const rule of detailRules) {
|
|
104
105
|
const memoryContent = generateMemoryFile(rule);
|
|
105
106
|
outputs.push({
|
|
106
107
|
tool: "claude",
|
|
107
|
-
filepath: (0, import_node_path2.join)(
|
|
108
|
+
filepath: (0, import_node_path2.join)(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
|
|
108
109
|
content: memoryContent
|
|
109
110
|
});
|
|
110
111
|
}
|
|
@@ -147,11 +148,12 @@ function generateMemoryFile(rule) {
|
|
|
147
148
|
|
|
148
149
|
// src/generators/cline.ts
|
|
149
150
|
var import_node_path3 = require("path");
|
|
150
|
-
async function generateClineConfig(rules, config) {
|
|
151
|
+
async function generateClineConfig(rules, config, baseDir) {
|
|
151
152
|
const outputs = [];
|
|
152
153
|
for (const rule of rules) {
|
|
153
154
|
const content = generateClineMarkdown(rule);
|
|
154
|
-
const
|
|
155
|
+
const outputDir = baseDir ? (0, import_node_path3.join)(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
|
|
156
|
+
const filepath = (0, import_node_path3.join)(outputDir, `${rule.filename}.md`);
|
|
155
157
|
outputs.push({
|
|
156
158
|
tool: "cline",
|
|
157
159
|
filepath,
|
|
@@ -166,12 +168,13 @@ function generateClineMarkdown(rule) {
|
|
|
166
168
|
|
|
167
169
|
// src/generators/copilot.ts
|
|
168
170
|
var import_node_path4 = require("path");
|
|
169
|
-
async function generateCopilotConfig(rules, config) {
|
|
171
|
+
async function generateCopilotConfig(rules, config, baseDir) {
|
|
170
172
|
const outputs = [];
|
|
171
173
|
for (const rule of rules) {
|
|
172
174
|
const content = generateCopilotMarkdown(rule);
|
|
173
175
|
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
174
|
-
const
|
|
176
|
+
const outputDir = baseDir ? (0, import_node_path4.join)(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
|
|
177
|
+
const filepath = (0, import_node_path4.join)(outputDir, `${baseFilename}.instructions.md`);
|
|
175
178
|
outputs.push({
|
|
176
179
|
tool: "copilot",
|
|
177
180
|
filepath,
|
|
@@ -196,11 +199,12 @@ function generateCopilotMarkdown(rule) {
|
|
|
196
199
|
|
|
197
200
|
// src/generators/cursor.ts
|
|
198
201
|
var import_node_path5 = require("path");
|
|
199
|
-
async function generateCursorConfig(rules, config) {
|
|
202
|
+
async function generateCursorConfig(rules, config, baseDir) {
|
|
200
203
|
const outputs = [];
|
|
201
204
|
for (const rule of rules) {
|
|
202
205
|
const content = generateCursorMarkdown(rule);
|
|
203
|
-
const
|
|
206
|
+
const outputDir = baseDir ? (0, import_node_path5.join)(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
|
|
207
|
+
const filepath = (0, import_node_path5.join)(outputDir, `${rule.filename}.mdc`);
|
|
204
208
|
outputs.push({
|
|
205
209
|
tool: "cursor",
|
|
206
210
|
filepath,
|
|
@@ -232,11 +236,12 @@ function generateCursorMarkdown(rule) {
|
|
|
232
236
|
|
|
233
237
|
// src/generators/roo.ts
|
|
234
238
|
var import_node_path6 = require("path");
|
|
235
|
-
async function generateRooConfig(rules, config) {
|
|
239
|
+
async function generateRooConfig(rules, config, baseDir) {
|
|
236
240
|
const outputs = [];
|
|
237
241
|
for (const rule of rules) {
|
|
238
242
|
const content = generateRooMarkdown(rule);
|
|
239
|
-
const
|
|
243
|
+
const outputDir = baseDir ? (0, import_node_path6.join)(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
|
|
244
|
+
const filepath = (0, import_node_path6.join)(outputDir, `${rule.filename}.md`);
|
|
240
245
|
outputs.push({
|
|
241
246
|
tool: "roo",
|
|
242
247
|
filepath,
|
|
@@ -317,7 +322,7 @@ async function removeClaudeGeneratedFiles() {
|
|
|
317
322
|
}
|
|
318
323
|
|
|
319
324
|
// src/core/generator.ts
|
|
320
|
-
async function generateConfigurations(rules, config, targetTools) {
|
|
325
|
+
async function generateConfigurations(rules, config, targetTools, baseDir) {
|
|
321
326
|
const outputs = [];
|
|
322
327
|
const toolsToGenerate = targetTools || config.defaultTargets;
|
|
323
328
|
for (const tool of toolsToGenerate) {
|
|
@@ -326,7 +331,7 @@ async function generateConfigurations(rules, config, targetTools) {
|
|
|
326
331
|
console.warn(`No rules found for tool: ${tool}`);
|
|
327
332
|
continue;
|
|
328
333
|
}
|
|
329
|
-
const toolOutputs = await generateForTool(tool, relevantRules, config);
|
|
334
|
+
const toolOutputs = await generateForTool(tool, relevantRules, config, baseDir);
|
|
330
335
|
if (toolOutputs) {
|
|
331
336
|
outputs.push(...toolOutputs);
|
|
332
337
|
}
|
|
@@ -339,18 +344,18 @@ function filterRulesForTool(rules, tool, config) {
|
|
|
339
344
|
return targets.includes(tool);
|
|
340
345
|
});
|
|
341
346
|
}
|
|
342
|
-
async function generateForTool(tool, rules, config) {
|
|
347
|
+
async function generateForTool(tool, rules, config, baseDir) {
|
|
343
348
|
switch (tool) {
|
|
344
349
|
case "copilot":
|
|
345
|
-
return generateCopilotConfig(rules, config);
|
|
350
|
+
return generateCopilotConfig(rules, config, baseDir);
|
|
346
351
|
case "cursor":
|
|
347
|
-
return generateCursorConfig(rules, config);
|
|
352
|
+
return generateCursorConfig(rules, config, baseDir);
|
|
348
353
|
case "cline":
|
|
349
|
-
return generateClineConfig(rules, config);
|
|
354
|
+
return generateClineConfig(rules, config, baseDir);
|
|
350
355
|
case "claude":
|
|
351
|
-
return await generateClaudeConfig(rules, config);
|
|
356
|
+
return await generateClaudeConfig(rules, config, baseDir);
|
|
352
357
|
case "roo":
|
|
353
|
-
return generateRooConfig(rules, config);
|
|
358
|
+
return generateRooConfig(rules, config, baseDir);
|
|
354
359
|
default:
|
|
355
360
|
console.warn(`Unknown tool: ${tool}`);
|
|
356
361
|
return null;
|
|
@@ -471,6 +476,7 @@ async function validateRule(rule) {
|
|
|
471
476
|
// src/cli/commands/generate.ts
|
|
472
477
|
async function generateCommand(options = {}) {
|
|
473
478
|
const config = getDefaultConfig();
|
|
479
|
+
const baseDirs = options.baseDirs || [process.cwd()];
|
|
474
480
|
console.log("Generating configuration files...");
|
|
475
481
|
if (!await fileExists(config.aiRulesDir)) {
|
|
476
482
|
console.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
@@ -487,6 +493,7 @@ async function generateCommand(options = {}) {
|
|
|
487
493
|
}
|
|
488
494
|
if (options.verbose) {
|
|
489
495
|
console.log(`Found ${rules.length} rule(s)`);
|
|
496
|
+
console.log(`Base directories: ${baseDirs.join(", ")}`);
|
|
490
497
|
}
|
|
491
498
|
if (options.delete) {
|
|
492
499
|
if (options.verbose) {
|
|
@@ -518,17 +525,31 @@ async function generateCommand(options = {}) {
|
|
|
518
525
|
console.log("Deleted existing output directories");
|
|
519
526
|
}
|
|
520
527
|
}
|
|
521
|
-
|
|
522
|
-
|
|
528
|
+
let totalOutputs = 0;
|
|
529
|
+
for (const baseDir of baseDirs) {
|
|
530
|
+
if (options.verbose) {
|
|
531
|
+
console.log(`
|
|
532
|
+
Generating configurations for base directory: ${baseDir}`);
|
|
533
|
+
}
|
|
534
|
+
const outputs = await generateConfigurations(rules, config, options.tools, baseDir);
|
|
535
|
+
if (outputs.length === 0) {
|
|
536
|
+
if (options.verbose) {
|
|
537
|
+
console.warn(`\u26A0\uFE0F No configurations generated for ${baseDir}`);
|
|
538
|
+
}
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
for (const output of outputs) {
|
|
542
|
+
await writeFileContent(output.filepath, output.content);
|
|
543
|
+
console.log(`\u2705 Generated ${output.tool} configuration: ${output.filepath}`);
|
|
544
|
+
}
|
|
545
|
+
totalOutputs += outputs.length;
|
|
546
|
+
}
|
|
547
|
+
if (totalOutputs === 0) {
|
|
523
548
|
console.warn("\u26A0\uFE0F No configurations generated");
|
|
524
549
|
return;
|
|
525
550
|
}
|
|
526
|
-
for (const output of outputs) {
|
|
527
|
-
await writeFileContent(output.filepath, output.content);
|
|
528
|
-
console.log(`\u2705 Generated ${output.tool} configuration: ${output.filepath}`);
|
|
529
|
-
}
|
|
530
551
|
console.log(`
|
|
531
|
-
\u{1F389} Successfully generated ${
|
|
552
|
+
\u{1F389} Successfully generated ${totalOutputs} configuration file(s)!`);
|
|
532
553
|
} catch (error) {
|
|
533
554
|
console.error("\u274C Failed to generate configurations:", error);
|
|
534
555
|
process.exit(1);
|
|
@@ -548,7 +569,15 @@ var gitignoreCommand = async () => {
|
|
|
548
569
|
".clinerules/",
|
|
549
570
|
"CLAUDE.md",
|
|
550
571
|
".claude/memories/",
|
|
551
|
-
".roo/rules/"
|
|
572
|
+
".roo/rules/",
|
|
573
|
+
"# Support for --base-dir option (any depth)",
|
|
574
|
+
"**/.github/copilot-instructions.md",
|
|
575
|
+
"**/.github/instructions/",
|
|
576
|
+
"**/.cursor/rules/",
|
|
577
|
+
"**/.clinerules/",
|
|
578
|
+
"**/CLAUDE.md",
|
|
579
|
+
"**/.claude/memories/",
|
|
580
|
+
"**/.roo/rules/"
|
|
552
581
|
];
|
|
553
582
|
let gitignoreContent = "";
|
|
554
583
|
if ((0, import_node_fs.existsSync)(gitignorePath)) {
|
|
@@ -814,7 +843,10 @@ program.name("rulesync").description("Unified AI rules management CLI tool").ver
|
|
|
814
843
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
815
844
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
816
845
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|
|
817
|
-
program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claude", "Generate only for Claude Code").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
846
|
+
program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claude", "Generate only for Claude Code").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
847
|
+
"-b, --base-dir <paths>",
|
|
848
|
+
"Base directories to generate files (comma-separated for multiple paths)"
|
|
849
|
+
).option("-v, --verbose", "Verbose output").action(async (options) => {
|
|
818
850
|
const tools = [];
|
|
819
851
|
if (options.copilot) tools.push("copilot");
|
|
820
852
|
if (options.cursor) tools.push("cursor");
|
|
@@ -827,6 +859,9 @@ program.command("generate").description("Generate configuration files for AI too
|
|
|
827
859
|
if (tools.length > 0) {
|
|
828
860
|
generateOptions.tools = tools;
|
|
829
861
|
}
|
|
862
|
+
if (options.baseDir) {
|
|
863
|
+
generateOptions.baseDirs = options.baseDir.split(",").map((dir) => dir.trim()).filter((dir) => dir.length > 0);
|
|
864
|
+
}
|
|
830
865
|
await generateCommand(generateOptions);
|
|
831
866
|
});
|
|
832
867
|
program.command("validate").description("Validate rulesync configuration").action(validateCommand);
|
package/dist/index.mjs
CHANGED
|
@@ -67,21 +67,22 @@ async function addCommand(filename) {
|
|
|
67
67
|
|
|
68
68
|
// src/generators/claude.ts
|
|
69
69
|
import { join } from "path";
|
|
70
|
-
async function generateClaudeConfig(rules, config) {
|
|
70
|
+
async function generateClaudeConfig(rules, config, baseDir) {
|
|
71
71
|
const outputs = [];
|
|
72
72
|
const rootRules = rules.filter((r) => r.frontmatter.root === true);
|
|
73
73
|
const detailRules = rules.filter((r) => r.frontmatter.root === false);
|
|
74
74
|
const claudeMdContent = generateClaudeMarkdown(rootRules, detailRules);
|
|
75
|
+
const claudeOutputDir = baseDir ? join(baseDir, config.outputPaths.claude) : config.outputPaths.claude;
|
|
75
76
|
outputs.push({
|
|
76
77
|
tool: "claude",
|
|
77
|
-
filepath: join(
|
|
78
|
+
filepath: join(claudeOutputDir, "CLAUDE.md"),
|
|
78
79
|
content: claudeMdContent
|
|
79
80
|
});
|
|
80
81
|
for (const rule of detailRules) {
|
|
81
82
|
const memoryContent = generateMemoryFile(rule);
|
|
82
83
|
outputs.push({
|
|
83
84
|
tool: "claude",
|
|
84
|
-
filepath: join(
|
|
85
|
+
filepath: join(claudeOutputDir, ".claude", "memories", `${rule.filename}.md`),
|
|
85
86
|
content: memoryContent
|
|
86
87
|
});
|
|
87
88
|
}
|
|
@@ -124,11 +125,12 @@ function generateMemoryFile(rule) {
|
|
|
124
125
|
|
|
125
126
|
// src/generators/cline.ts
|
|
126
127
|
import { join as join2 } from "path";
|
|
127
|
-
async function generateClineConfig(rules, config) {
|
|
128
|
+
async function generateClineConfig(rules, config, baseDir) {
|
|
128
129
|
const outputs = [];
|
|
129
130
|
for (const rule of rules) {
|
|
130
131
|
const content = generateClineMarkdown(rule);
|
|
131
|
-
const
|
|
132
|
+
const outputDir = baseDir ? join2(baseDir, config.outputPaths.cline) : config.outputPaths.cline;
|
|
133
|
+
const filepath = join2(outputDir, `${rule.filename}.md`);
|
|
132
134
|
outputs.push({
|
|
133
135
|
tool: "cline",
|
|
134
136
|
filepath,
|
|
@@ -143,12 +145,13 @@ function generateClineMarkdown(rule) {
|
|
|
143
145
|
|
|
144
146
|
// src/generators/copilot.ts
|
|
145
147
|
import { join as join3 } from "path";
|
|
146
|
-
async function generateCopilotConfig(rules, config) {
|
|
148
|
+
async function generateCopilotConfig(rules, config, baseDir) {
|
|
147
149
|
const outputs = [];
|
|
148
150
|
for (const rule of rules) {
|
|
149
151
|
const content = generateCopilotMarkdown(rule);
|
|
150
152
|
const baseFilename = rule.filename.replace(/\.md$/, "");
|
|
151
|
-
const
|
|
153
|
+
const outputDir = baseDir ? join3(baseDir, config.outputPaths.copilot) : config.outputPaths.copilot;
|
|
154
|
+
const filepath = join3(outputDir, `${baseFilename}.instructions.md`);
|
|
152
155
|
outputs.push({
|
|
153
156
|
tool: "copilot",
|
|
154
157
|
filepath,
|
|
@@ -173,11 +176,12 @@ function generateCopilotMarkdown(rule) {
|
|
|
173
176
|
|
|
174
177
|
// src/generators/cursor.ts
|
|
175
178
|
import { join as join4 } from "path";
|
|
176
|
-
async function generateCursorConfig(rules, config) {
|
|
179
|
+
async function generateCursorConfig(rules, config, baseDir) {
|
|
177
180
|
const outputs = [];
|
|
178
181
|
for (const rule of rules) {
|
|
179
182
|
const content = generateCursorMarkdown(rule);
|
|
180
|
-
const
|
|
183
|
+
const outputDir = baseDir ? join4(baseDir, config.outputPaths.cursor) : config.outputPaths.cursor;
|
|
184
|
+
const filepath = join4(outputDir, `${rule.filename}.mdc`);
|
|
181
185
|
outputs.push({
|
|
182
186
|
tool: "cursor",
|
|
183
187
|
filepath,
|
|
@@ -209,11 +213,12 @@ function generateCursorMarkdown(rule) {
|
|
|
209
213
|
|
|
210
214
|
// src/generators/roo.ts
|
|
211
215
|
import { join as join5 } from "path";
|
|
212
|
-
async function generateRooConfig(rules, config) {
|
|
216
|
+
async function generateRooConfig(rules, config, baseDir) {
|
|
213
217
|
const outputs = [];
|
|
214
218
|
for (const rule of rules) {
|
|
215
219
|
const content = generateRooMarkdown(rule);
|
|
216
|
-
const
|
|
220
|
+
const outputDir = baseDir ? join5(baseDir, config.outputPaths.roo) : config.outputPaths.roo;
|
|
221
|
+
const filepath = join5(outputDir, `${rule.filename}.md`);
|
|
217
222
|
outputs.push({
|
|
218
223
|
tool: "roo",
|
|
219
224
|
filepath,
|
|
@@ -294,7 +299,7 @@ async function removeClaudeGeneratedFiles() {
|
|
|
294
299
|
}
|
|
295
300
|
|
|
296
301
|
// src/core/generator.ts
|
|
297
|
-
async function generateConfigurations(rules, config, targetTools) {
|
|
302
|
+
async function generateConfigurations(rules, config, targetTools, baseDir) {
|
|
298
303
|
const outputs = [];
|
|
299
304
|
const toolsToGenerate = targetTools || config.defaultTargets;
|
|
300
305
|
for (const tool of toolsToGenerate) {
|
|
@@ -303,7 +308,7 @@ async function generateConfigurations(rules, config, targetTools) {
|
|
|
303
308
|
console.warn(`No rules found for tool: ${tool}`);
|
|
304
309
|
continue;
|
|
305
310
|
}
|
|
306
|
-
const toolOutputs = await generateForTool(tool, relevantRules, config);
|
|
311
|
+
const toolOutputs = await generateForTool(tool, relevantRules, config, baseDir);
|
|
307
312
|
if (toolOutputs) {
|
|
308
313
|
outputs.push(...toolOutputs);
|
|
309
314
|
}
|
|
@@ -316,18 +321,18 @@ function filterRulesForTool(rules, tool, config) {
|
|
|
316
321
|
return targets.includes(tool);
|
|
317
322
|
});
|
|
318
323
|
}
|
|
319
|
-
async function generateForTool(tool, rules, config) {
|
|
324
|
+
async function generateForTool(tool, rules, config, baseDir) {
|
|
320
325
|
switch (tool) {
|
|
321
326
|
case "copilot":
|
|
322
|
-
return generateCopilotConfig(rules, config);
|
|
327
|
+
return generateCopilotConfig(rules, config, baseDir);
|
|
323
328
|
case "cursor":
|
|
324
|
-
return generateCursorConfig(rules, config);
|
|
329
|
+
return generateCursorConfig(rules, config, baseDir);
|
|
325
330
|
case "cline":
|
|
326
|
-
return generateClineConfig(rules, config);
|
|
331
|
+
return generateClineConfig(rules, config, baseDir);
|
|
327
332
|
case "claude":
|
|
328
|
-
return await generateClaudeConfig(rules, config);
|
|
333
|
+
return await generateClaudeConfig(rules, config, baseDir);
|
|
329
334
|
case "roo":
|
|
330
|
-
return generateRooConfig(rules, config);
|
|
335
|
+
return generateRooConfig(rules, config, baseDir);
|
|
331
336
|
default:
|
|
332
337
|
console.warn(`Unknown tool: ${tool}`);
|
|
333
338
|
return null;
|
|
@@ -448,6 +453,7 @@ async function validateRule(rule) {
|
|
|
448
453
|
// src/cli/commands/generate.ts
|
|
449
454
|
async function generateCommand(options = {}) {
|
|
450
455
|
const config = getDefaultConfig();
|
|
456
|
+
const baseDirs = options.baseDirs || [process.cwd()];
|
|
451
457
|
console.log("Generating configuration files...");
|
|
452
458
|
if (!await fileExists(config.aiRulesDir)) {
|
|
453
459
|
console.error("\u274C .rulesync directory not found. Run 'rulesync init' first.");
|
|
@@ -464,6 +470,7 @@ async function generateCommand(options = {}) {
|
|
|
464
470
|
}
|
|
465
471
|
if (options.verbose) {
|
|
466
472
|
console.log(`Found ${rules.length} rule(s)`);
|
|
473
|
+
console.log(`Base directories: ${baseDirs.join(", ")}`);
|
|
467
474
|
}
|
|
468
475
|
if (options.delete) {
|
|
469
476
|
if (options.verbose) {
|
|
@@ -495,17 +502,31 @@ async function generateCommand(options = {}) {
|
|
|
495
502
|
console.log("Deleted existing output directories");
|
|
496
503
|
}
|
|
497
504
|
}
|
|
498
|
-
|
|
499
|
-
|
|
505
|
+
let totalOutputs = 0;
|
|
506
|
+
for (const baseDir of baseDirs) {
|
|
507
|
+
if (options.verbose) {
|
|
508
|
+
console.log(`
|
|
509
|
+
Generating configurations for base directory: ${baseDir}`);
|
|
510
|
+
}
|
|
511
|
+
const outputs = await generateConfigurations(rules, config, options.tools, baseDir);
|
|
512
|
+
if (outputs.length === 0) {
|
|
513
|
+
if (options.verbose) {
|
|
514
|
+
console.warn(`\u26A0\uFE0F No configurations generated for ${baseDir}`);
|
|
515
|
+
}
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
for (const output of outputs) {
|
|
519
|
+
await writeFileContent(output.filepath, output.content);
|
|
520
|
+
console.log(`\u2705 Generated ${output.tool} configuration: ${output.filepath}`);
|
|
521
|
+
}
|
|
522
|
+
totalOutputs += outputs.length;
|
|
523
|
+
}
|
|
524
|
+
if (totalOutputs === 0) {
|
|
500
525
|
console.warn("\u26A0\uFE0F No configurations generated");
|
|
501
526
|
return;
|
|
502
527
|
}
|
|
503
|
-
for (const output of outputs) {
|
|
504
|
-
await writeFileContent(output.filepath, output.content);
|
|
505
|
-
console.log(`\u2705 Generated ${output.tool} configuration: ${output.filepath}`);
|
|
506
|
-
}
|
|
507
528
|
console.log(`
|
|
508
|
-
\u{1F389} Successfully generated ${
|
|
529
|
+
\u{1F389} Successfully generated ${totalOutputs} configuration file(s)!`);
|
|
509
530
|
} catch (error) {
|
|
510
531
|
console.error("\u274C Failed to generate configurations:", error);
|
|
511
532
|
process.exit(1);
|
|
@@ -525,7 +546,15 @@ var gitignoreCommand = async () => {
|
|
|
525
546
|
".clinerules/",
|
|
526
547
|
"CLAUDE.md",
|
|
527
548
|
".claude/memories/",
|
|
528
|
-
".roo/rules/"
|
|
549
|
+
".roo/rules/",
|
|
550
|
+
"# Support for --base-dir option (any depth)",
|
|
551
|
+
"**/.github/copilot-instructions.md",
|
|
552
|
+
"**/.github/instructions/",
|
|
553
|
+
"**/.cursor/rules/",
|
|
554
|
+
"**/.clinerules/",
|
|
555
|
+
"**/CLAUDE.md",
|
|
556
|
+
"**/.claude/memories/",
|
|
557
|
+
"**/.roo/rules/"
|
|
529
558
|
];
|
|
530
559
|
let gitignoreContent = "";
|
|
531
560
|
if (existsSync(gitignorePath)) {
|
|
@@ -791,7 +820,10 @@ program.name("rulesync").description("Unified AI rules management CLI tool").ver
|
|
|
791
820
|
program.command("init").description("Initialize rulesync in current directory").action(initCommand);
|
|
792
821
|
program.command("add <filename>").description("Add a new rule file").action(addCommand);
|
|
793
822
|
program.command("gitignore").description("Add generated files to .gitignore").action(gitignoreCommand);
|
|
794
|
-
program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claude", "Generate only for Claude Code").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
823
|
+
program.command("generate").description("Generate configuration files for AI tools").option("--copilot", "Generate only for GitHub Copilot").option("--cursor", "Generate only for Cursor").option("--cline", "Generate only for Cline").option("--claude", "Generate only for Claude Code").option("--delete", "Delete all existing files in output directories before generating").option(
|
|
824
|
+
"-b, --base-dir <paths>",
|
|
825
|
+
"Base directories to generate files (comma-separated for multiple paths)"
|
|
826
|
+
).option("-v, --verbose", "Verbose output").action(async (options) => {
|
|
795
827
|
const tools = [];
|
|
796
828
|
if (options.copilot) tools.push("copilot");
|
|
797
829
|
if (options.cursor) tools.push("cursor");
|
|
@@ -804,6 +836,9 @@ program.command("generate").description("Generate configuration files for AI too
|
|
|
804
836
|
if (tools.length > 0) {
|
|
805
837
|
generateOptions.tools = tools;
|
|
806
838
|
}
|
|
839
|
+
if (options.baseDir) {
|
|
840
|
+
generateOptions.baseDirs = options.baseDir.split(",").map((dir) => dir.trim()).filter((dir) => dir.length > 0);
|
|
841
|
+
}
|
|
807
842
|
await generateCommand(generateOptions);
|
|
808
843
|
});
|
|
809
844
|
program.command("validate").description("Validate rulesync configuration").action(validateCommand);
|
package/package.json
CHANGED