Skip to content

Commit ff8ec52

Browse files
authored
Use a .kilocodemodes file to prevent conflicts with other extensions (#44)
1 parent 4aad760 commit ff8ec52

File tree

6 files changed

+26
-26
lines changed

6 files changed

+26
-26
lines changed

.roomodes .kilocodemodes

File renamed without changes.

.vscodeignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ demo.gif
2424
.gitattributes
2525
.prettierignore
2626
.clinerules*
27-
.roomodes
27+
.kilocodemodes
2828
cline_docs/**
2929
coverage/**
3030

src/core/config/CustomModesManager.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { fileExistsAtPath } from "../../utils/fs"
77
import { arePathsEqual } from "../../utils/path"
88
import { logger } from "../../utils/logging"
99

10-
const ROOMODES_FILENAME = ".roomodes"
10+
const ROOMODES_FILENAME = ".kilocodemodes"
1111

1212
export class CustomModesManager {
1313
private disposables: vscode.Disposable[] = []
@@ -149,27 +149,27 @@ export class CustomModesManager {
149149
return
150150
}
151151

152-
// Get modes from .roomodes if it exists (takes precedence)
152+
// Get modes from .kilocodemodes if it exists (takes precedence)
153153
const roomodesPath = await this.getWorkspaceRoomodes()
154154
const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : []
155155

156-
// Merge modes from both sources (.roomodes takes precedence)
156+
// Merge modes from both sources (.kilocodemodes takes precedence)
157157
const mergedModes = await this.mergeCustomModes(roomodesModes, result.data.customModes)
158158
await this.context.globalState.update("customModes", mergedModes)
159159
await this.onUpdate()
160160
}
161161
}),
162162
)
163163

164-
// Watch .roomodes file if it exists
164+
// Watch .kilocodemodes file if it exists
165165
const roomodesPath = await this.getWorkspaceRoomodes()
166166
if (roomodesPath) {
167167
this.disposables.push(
168168
vscode.workspace.onDidSaveTextDocument(async (document) => {
169169
if (arePathsEqual(document.uri.fsPath, roomodesPath)) {
170170
const settingsModes = await this.loadModesFromFile(settingsPath)
171171
const roomodesModes = await this.loadModesFromFile(roomodesPath)
172-
// .roomodes takes precedence
172+
// .kilocodemodes takes precedence
173173
const mergedModes = await this.mergeCustomModes(roomodesModes, settingsModes)
174174
await this.context.globalState.update("customModes", mergedModes)
175175
await this.onUpdate()
@@ -184,7 +184,7 @@ export class CustomModesManager {
184184
const settingsPath = await this.getCustomModesFilePath()
185185
const settingsModes = await this.loadModesFromFile(settingsPath)
186186

187-
// Get modes from .roomodes if it exists
187+
// Get modes from .kilocodemodes if it exists
188188
const roomodesPath = await this.getWorkspaceRoomodes()
189189
const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : []
190190

src/core/config/__tests__/CustomModesManager.test.ts

+13-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe("CustomModesManager", () => {
2020
// Use path.sep to ensure correct path separators for the current platform
2121
const mockStoragePath = `${path.sep}mock${path.sep}settings`
2222
const mockSettingsPath = path.join(mockStoragePath, "settings", "cline_custom_modes.json")
23-
const mockRoomodes = `${path.sep}mock${path.sep}workspace${path.sep}.roomodes`
23+
const mockRoomodes = `${path.sep}mock${path.sep}workspace${path.sep}.kilocodemodes`
2424

2525
beforeEach(() => {
2626
mockOnUpdate = jest.fn()
@@ -56,7 +56,7 @@ describe("CustomModesManager", () => {
5656
})
5757

5858
describe("getCustomModes", () => {
59-
it("should merge modes with .roomodes taking precedence", async () => {
59+
it("should merge modes with .kilocodemodes taking precedence", async () => {
6060
const settingsModes = [
6161
{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] },
6262
{ slug: "mode2", name: "Mode 2", roleDefinition: "Role 2", groups: ["read"] },
@@ -83,13 +83,13 @@ describe("CustomModesManager", () => {
8383
expect(modes).toHaveLength(3)
8484
expect(modes.map((m) => m.slug)).toEqual(["mode2", "mode3", "mode1"])
8585

86-
// mode2 should come from .roomodes since it takes precedence
86+
// mode2 should come from .kilocodemodes since it takes precedence
8787
const mode2 = modes.find((m) => m.slug === "mode2")
8888
expect(mode2?.name).toBe("Mode 2 Override")
8989
expect(mode2?.roleDefinition).toBe("Role 2 Override")
9090
})
9191

92-
it("should handle missing .roomodes file", async () => {
92+
it("should handle missing .kilocodemodes file", async () => {
9393
const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }]
9494

9595
;(fileExistsAtPath as jest.Mock).mockImplementation(async (path: string) => {
@@ -108,7 +108,7 @@ describe("CustomModesManager", () => {
108108
expect(modes[0].slug).toBe("mode1")
109109
})
110110

111-
it("should handle invalid JSON in .roomodes", async () => {
111+
it("should handle invalid JSON in .kilocodemodes", async () => {
112112
const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }]
113113

114114
;(fs.readFile as jest.Mock).mockImplementation(async (path: string) => {
@@ -123,14 +123,14 @@ describe("CustomModesManager", () => {
123123

124124
const modes = await manager.getCustomModes()
125125

126-
// Should fall back to settings modes when .roomodes is invalid
126+
// Should fall back to settings modes when .kilocodemodes is invalid
127127
expect(modes).toHaveLength(1)
128128
expect(modes[0].slug).toBe("mode1")
129129
})
130130
})
131131

132132
describe("updateCustomMode", () => {
133-
it("should update mode in settings file while preserving .roomodes precedence", async () => {
133+
it("should update mode in settings file while preserving .kilocodemodes precedence", async () => {
134134
const newMode: ModeConfig = {
135135
slug: "mode1",
136136
name: "Updated Mode 1",
@@ -194,13 +194,13 @@ describe("CustomModesManager", () => {
194194
}),
195195
)
196196

197-
// Should update global state with merged modes where .roomodes takes precedence
197+
// Should update global state with merged modes where .kilocodemodes takes precedence
198198
expect(mockContext.globalState.update).toHaveBeenCalledWith(
199199
"customModes",
200200
expect.arrayContaining([
201201
expect.objectContaining({
202202
slug: "mode1",
203-
name: "Roomodes Mode 1", // .roomodes version should take precedence
203+
name: "Roomodes Mode 1", // .kilocodemodes version should take precedence
204204
source: "project",
205205
}),
206206
]),
@@ -210,7 +210,7 @@ describe("CustomModesManager", () => {
210210
expect(mockOnUpdate).toHaveBeenCalled()
211211
})
212212

213-
it("creates .roomodes file when adding project-specific mode", async () => {
213+
it("creates .kilocodemodes file when adding project-specific mode", async () => {
214214
const projectMode: ModeConfig = {
215215
slug: "project-mode",
216216
name: "Project Mode",
@@ -219,7 +219,7 @@ describe("CustomModesManager", () => {
219219
source: "project",
220220
}
221221

222-
// Mock .roomodes to not exist initially
222+
// Mock .kilocodemodes to not exist initially
223223
let roomodesContent: any = null
224224
;(fileExistsAtPath as jest.Mock).mockImplementation(async (path: string) => {
225225
return path === mockSettingsPath
@@ -245,7 +245,7 @@ describe("CustomModesManager", () => {
245245

246246
await manager.updateCustomMode("project-mode", projectMode)
247247

248-
// Verify .roomodes was created with the project mode
248+
// Verify .kilocodemodes was created with the project mode
249249
expect(fs.writeFile).toHaveBeenCalledWith(
250250
expect.any(String), // Don't check exact path as it may have different separators on different platforms
251251
expect.stringContaining("project-mode"),
@@ -256,7 +256,7 @@ describe("CustomModesManager", () => {
256256
const writeCall = (fs.writeFile as jest.Mock).mock.calls[0]
257257
expect(path.normalize(writeCall[0])).toBe(path.normalize(mockRoomodes))
258258

259-
// Verify the content written to .roomodes
259+
// Verify the content written to .kilocodemodes
260260
expect(roomodesContent).toEqual({
261261
customModes: [
262262
expect.objectContaining({

src/core/prompts/sections/modes.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ ${allModes.map((mode: ModeConfig) => ` * "${mode.name}" mode (${mode.slug}) - $
2727
2828
- Custom modes can be configured in two ways:
2929
1. Globally via '${customModesPath}' (created automatically on startup)
30-
2. Per-workspace via '.roomodes' in the workspace root directory
30+
2. Per-workspace via '.kilocodemodes' in the workspace root directory
3131
32-
When modes with the same slug exist in both files, the workspace-specific .roomodes version takes precedence. This allows projects to override global modes or define project-specific modes.
32+
When modes with the same slug exist in both files, the workspace-specific .kilocodemodes version takes precedence. This allows projects to override global modes or define project-specific modes.
3333
34-
If asked to create a project mode, create it in .roomodes in the workspace root. If asked to create a global mode, use the global custom modes file.
34+
If asked to create a project mode, create it in .kilocode in the workspace root. If asked to create a global mode, use the global custom modes file.
3535
3636
- The following fields are required and must not be empty:
3737
* slug: A valid slug (lowercase letters, numbers, and hyphens). Must be unique, and shorter is better.

webview-ui/src/components/prompts/PromptsView.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
456456
e.preventDefault() // Prevent blur
457457
vscode.postMessage({
458458
type: "openFile",
459-
text: "./.roomodes",
459+
text: "./.kilocodemodes",
460460
values: {
461461
create: true,
462462
content: JSON.stringify({ customModes: [] }, null, 2),
@@ -465,7 +465,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
465465
setShowConfigMenu(false)
466466
}}
467467
onClick={(e) => e.preventDefault()}>
468-
Edit Project Modes (.roomodes)
468+
Edit Project Modes (.kilocodemodes)
469469
</div>
470470
</div>
471471
)}
@@ -1225,7 +1225,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
12251225
</div>
12261226
</VSCodeRadio>
12271227
<VSCodeRadio value="project">
1228-
Project-specific (.roomodes)
1228+
Project-specific (.kilocodemodes)
12291229
<div className="text-xs text-vscode-descriptionForeground mt-0.5">
12301230
Only available in this workspace, takes precedence over global
12311231
</div>

0 commit comments

Comments
 (0)