Skip to content

Commit 72498ef

Browse files
committed
feat: Add support for .roorules configuration files
- Add .roorules to the list of supported rule files - Improve mode-specific rule file handling to prioritize .roorules over .clinerules - Update file loading logic to track which rule file was successfully loaded - Add test cases for .roorules functionality This change maintains backward compatibility with existing .clinerules while introducing support for the new .roorules format as the preferred configuration method.
1 parent 72d1a90 commit 72498ef

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed

src/core/prompts/sections/__tests__/custom-instructions.test.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ describe("loadRuleFiles", () => {
1515
const result = await loadRuleFiles("/fake/path")
1616
expect(mockedFs.readFile).toHaveBeenCalled()
1717
expect(result).toBe(
18-
"\n# Rules from .clinerules:\ncontent with spaces\n" +
18+
"\n# Rules from .roorules:\ncontent with spaces\n" +
19+
"\n# Rules from .clinerules:\ncontent with spaces\n" +
1920
"\n# Rules from .cursorrules:\ncontent with spaces\n" +
2021
"\n# Rules from .windsurfrules:\ncontent with spaces\n",
2122
)
@@ -51,6 +52,9 @@ describe("loadRuleFiles", () => {
5152

5253
it("should combine content from multiple rule files when they exist", async () => {
5354
mockedFs.readFile.mockImplementation(((filePath: string | Buffer | URL | number) => {
55+
if (filePath.toString().endsWith(".roorules")) {
56+
return Promise.resolve("roo rules content")
57+
}
5458
if (filePath.toString().endsWith(".clinerules")) {
5559
return Promise.resolve("cline rules content")
5660
}
@@ -62,7 +66,8 @@ describe("loadRuleFiles", () => {
6266

6367
const result = await loadRuleFiles("/fake/path")
6468
expect(result).toBe(
65-
"\n# Rules from .clinerules:\ncline rules content\n" +
69+
"\n# Rules from .roorules:\nroo rules content\n" +
70+
"\n# Rules from .clinerules:\ncline rules content\n" +
6671
"\n# Rules from .cursorrules:\ncursor rules content\n",
6772
)
6873
})
@@ -86,6 +91,9 @@ describe("loadRuleFiles", () => {
8691

8792
it("should skip directories with same name as rule files", async () => {
8893
mockedFs.readFile.mockImplementation(((filePath: string | Buffer | URL | number) => {
94+
if (filePath.toString().endsWith(".roorules")) {
95+
return Promise.reject({ code: "EISDIR" })
96+
}
8997
if (filePath.toString().endsWith(".clinerules")) {
9098
return Promise.reject({ code: "EISDIR" })
9199
}
@@ -121,7 +129,7 @@ describe("addCustomInstructions", () => {
121129
expect(result).toContain("(es)") // Check for language code in parentheses
122130
expect(result).toContain("Global Instructions:\nglobal instructions")
123131
expect(result).toContain("Mode-specific Instructions:\nmode instructions")
124-
expect(result).toContain("Rules from .clinerules-test-mode:\nmode specific rules")
132+
expect(result).toContain("Rules from .roorules-test-mode:\nmode specific rules")
125133
})
126134

127135
it("should return empty string when no instructions provided", async () => {

src/core/prompts/sections/custom-instructions.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async function safeReadFile(filePath: string): Promise<string> {
1717
}
1818

1919
export async function loadRuleFiles(cwd: string): Promise<string> {
20-
const ruleFiles = [".clinerules", ".cursorrules", ".windsurfrules"]
20+
const ruleFiles = [".roorules", ".clinerules", ".cursorrules", ".windsurfrules"]
2121
let combinedRules = ""
2222

2323
for (const file of ruleFiles) {
@@ -41,9 +41,19 @@ export async function addCustomInstructions(
4141

4242
// Load mode-specific rules if mode is provided
4343
let modeRuleContent = ""
44+
let usedRuleFile = ""
4445
if (mode) {
45-
const modeRuleFile = `.clinerules-${mode}`
46-
modeRuleContent = await safeReadFile(path.join(cwd, modeRuleFile))
46+
const rooModeRuleFile = `.roorules-${mode}`
47+
modeRuleContent = await safeReadFile(path.join(cwd, rooModeRuleFile))
48+
if (modeRuleContent) {
49+
usedRuleFile = rooModeRuleFile
50+
} else {
51+
const clineModeRuleFile = `.clinerules-${mode}`
52+
modeRuleContent = await safeReadFile(path.join(cwd, clineModeRuleFile))
53+
if (modeRuleContent) {
54+
usedRuleFile = clineModeRuleFile
55+
}
56+
}
4757
}
4858

4959
// Add language preference if provided
@@ -69,8 +79,7 @@ export async function addCustomInstructions(
6979

7080
// Add mode-specific rules first if they exist
7181
if (modeRuleContent && modeRuleContent.trim()) {
72-
const modeRuleFile = `.clinerules-${mode}`
73-
rules.push(`# Rules from ${modeRuleFile}:\n${modeRuleContent}`)
82+
rules.push(`# Rules from ${usedRuleFile}:\n${modeRuleContent}`)
7483
}
7584

7685
if (options.rooIgnoreInstructions) {

0 commit comments

Comments
 (0)