Skip to content

Commit c8b234a

Browse files
Add delete rule button (RooCodeInc#2958)
* add a delete button to the cline rules modal * changeset
1 parent 022fdf4 commit c8b234a

File tree

7 files changed

+94
-3
lines changed

7 files changed

+94
-3
lines changed

.changeset/eight-ears-flash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": minor
3+
---
4+
5+
Add a delete button to the Cline Rules modal to delete rule files

src/core/context/instructions/user-instructions/cline-rules.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,49 @@ export async function refreshClineRulesToggles(
173173
localToggles: updatedLocalToggles,
174174
}
175175
}
176+
177+
export async function deleteRuleFile(
178+
context: vscode.ExtensionContext,
179+
rulePath: string,
180+
isGlobal: boolean,
181+
): Promise<{ success: boolean; message: string }> {
182+
try {
183+
// Check if file exists
184+
const fileExists = await fileExistsAtPath(rulePath)
185+
if (!fileExists) {
186+
return {
187+
success: false,
188+
message: `Rule file does not exist: ${rulePath}`,
189+
}
190+
}
191+
192+
// Delete the file from disk
193+
await fs.unlink(rulePath)
194+
195+
// Get the filename for messages
196+
const fileName = path.basename(rulePath)
197+
198+
// Update the appropriate toggles
199+
if (isGlobal) {
200+
const toggles = ((await getGlobalState(context, "globalClineRulesToggles")) as ClineRulesToggles) || {}
201+
delete toggles[rulePath]
202+
await updateGlobalState(context, "globalClineRulesToggles", toggles)
203+
} else {
204+
const toggles = ((await getWorkspaceState(context, "localClineRulesToggles")) as ClineRulesToggles) || {}
205+
delete toggles[rulePath]
206+
await updateWorkspaceState(context, "localClineRulesToggles", toggles)
207+
}
208+
209+
return {
210+
success: true,
211+
message: `Rule file "${fileName}" deleted successfully`,
212+
}
213+
} catch (error) {
214+
const errorMessage = error instanceof Error ? error.message : String(error)
215+
console.error(`Error deleting rule file: ${errorMessage}`, error)
216+
return {
217+
success: false,
218+
message: `Failed to delete rule file.`,
219+
}
220+
}
221+
}

src/core/controller/index.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import {
4949
} from "../storage/state"
5050
import { Task, cwd } from "../task"
5151
import { ClineRulesToggles } from "../../shared/cline-rules"
52-
import { refreshClineRulesToggles } from "../context/instructions/user-instructions/cline-rules"
52+
import { deleteRuleFile, refreshClineRulesToggles } from "../context/instructions/user-instructions/cline-rules"
5353

5454
/*
5555
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
@@ -634,6 +634,24 @@ export class Controller {
634634
}
635635
break
636636
}
637+
case "deleteClineRule": {
638+
const { isGlobal, rulePath } = message
639+
if (rulePath && typeof isGlobal === "boolean") {
640+
const result = await deleteRuleFile(this.context, rulePath, isGlobal)
641+
if (result.success) {
642+
await refreshClineRulesToggles(this.context, cwd)
643+
await this.postStateToWebview()
644+
} else {
645+
console.error("Failed to delete rule file:", result.message)
646+
}
647+
} else {
648+
console.error("deleteClineRule: Missing or invalid parameters", {
649+
rulePath,
650+
isGlobal: typeof isGlobal === "boolean" ? isGlobal : `Invalid: ${typeof isGlobal}`,
651+
})
652+
}
653+
break
654+
}
637655
case "requestTotalTasksSize": {
638656
this.refreshTotalTasksSize()
639657
break

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export interface WebviewMessage {
8282
| "toggleFavoriteModel"
8383
| "grpc_request"
8484
| "toggleClineRule"
85+
| "deleteClineRule"
8586

8687
// | "relaunchChromeDebugMode"
8788
text?: string

webview-ui/src/components/cline-rules/ClineRulesToggleModal.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ const ClineRulesToggleModal: React.FC = () => {
111111
<RulesToggleList
112112
rules={globalRules}
113113
toggleRule={(rulePath, enabled) => toggleRule(true, rulePath, enabled)}
114+
isGlobal={true}
114115
listGap="small"
115116
/>
116117
</div>
@@ -121,6 +122,7 @@ const ClineRulesToggleModal: React.FC = () => {
121122
<RulesToggleList
122123
rules={localRules}
123124
toggleRule={(rulePath, enabled) => toggleRule(false, rulePath, enabled)}
125+
isGlobal={false}
124126
listGap="small"
125127
/>
126128
</div>

webview-ui/src/components/cline-rules/RuleRow.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
44
const RuleRow: React.FC<{
55
rulePath: string
66
enabled: boolean
7+
isGlobal: boolean
78
toggleRule: (rulePath: string, enabled: boolean) => void
8-
}> = ({ rulePath, enabled, toggleRule }) => {
9+
}> = ({ rulePath, enabled, isGlobal, toggleRule }) => {
910
// Get the filename from the path for display
1011
const displayName = rulePath.split("/").pop() || rulePath
1112

@@ -16,6 +17,14 @@ const RuleRow: React.FC<{
1617
})
1718
}
1819

20+
const handleDeleteClick = () => {
21+
vscode.postMessage({
22+
type: "deleteClineRule",
23+
rulePath: rulePath,
24+
isGlobal: isGlobal,
25+
})
26+
}
27+
1928
return (
2029
<div className="mb-2.5">
2130
<div
@@ -58,6 +67,14 @@ const RuleRow: React.FC<{
5867
style={{ height: "20px" }}>
5968
<span className="codicon codicon-edit" style={{ fontSize: "14px" }} />
6069
</VSCodeButton>
70+
<VSCodeButton
71+
appearance="icon"
72+
aria-label="Delete rule file"
73+
title="Delete rule file"
74+
onClick={handleDeleteClick}
75+
style={{ height: "20px" }}>
76+
<span className="codicon codicon-trash" style={{ fontSize: "14px" }} />
77+
</VSCodeButton>
6178
</div>
6279
</div>
6380
</div>

webview-ui/src/components/cline-rules/RulesToggleList.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import RuleRow from "./RuleRow"
33
const RulesToggleList = ({
44
rules,
55
toggleRule,
6+
isGlobal,
67
listGap = "medium",
78
}: {
89
rules: [string, boolean][]
910
toggleRule: (rulePath: string, enabled: boolean) => void
11+
isGlobal: boolean
1012
listGap?: "small" | "medium" | "large"
1113
}) => {
1214
const gapClasses = {
@@ -20,7 +22,7 @@ const RulesToggleList = ({
2022
return rules.length > 0 ? (
2123
<div className={`flex flex-col ${gapClass}`}>
2224
{rules.map(([rulePath, enabled]) => (
23-
<RuleRow key={rulePath} rulePath={rulePath} enabled={enabled} toggleRule={toggleRule} />
25+
<RuleRow key={rulePath} rulePath={rulePath} enabled={enabled} isGlobal={isGlobal} toggleRule={toggleRule} />
2426
))}
2527
</div>
2628
) : (

0 commit comments

Comments
 (0)