## For All Settings
1. Add the setting to schema definitions:
- Add the item to `globalSettingsSchema` in `src/schemas/index.ts`
- Add the item to `globalSettingsRecord` in `src/schemas/index.ts`
- Example: `terminalCommandDelay: z.number().optional(),`
2. Add the setting to type definitions:
- Add the item to `src/exports/types.ts`
- Add the item to `src/exports/roo-code.d.ts`
- Add the setting to `src/shared/ExtensionMessage.ts`
- Add the setting to the WebviewMessage type in `src/shared/WebviewMessage.ts`
- Example: `terminalCommandDelay?: number | undefined`
3. Add test coverage:
- Add the setting to mockState in src/core/webview/**tests**/ClineProvider.test.ts
- Add test cases for setting persistence and state updates
- Ensure all tests pass before submitting changes
## For Checkbox Settings
1. Add the message type to src/shared/WebviewMessage.ts:
- Add the setting name to the WebviewMessage type's type union
- Example: `| "multisearchDiffEnabled"`
2. Add the setting to webview-ui/src/context/ExtensionStateContext.tsx:
- Add the setting to the ExtensionStateContextType interface
- Add the setter function to the interface
- Add the setting to the initial state in useState
- Add the setting to the contextValue object
- Example:
```typescript
interface ExtensionStateContextType {
multisearchDiffEnabled: boolean
setMultisearchDiffEnabled: (value: boolean) => void
}
```
3. Add the setting to src/core/webview/ClineProvider.ts:
- Add the setting name to the GlobalStateKey type union
- Add the setting to the Promise.all array in getState
- Add the setting to the return value in getState with a default value
- Add the setting to the destructured variables in getStateToPostToWebview
- Add the setting to the return value in getStateToPostToWebview
- Add a case in setWebviewMessageListener to handle the setting's message type
- Example:
```typescript
case "multisearchDiffEnabled":
await this.updateGlobalState("multisearchDiffEnabled", message.bool)
await this.postStateToWebview()
break
```
4. Add the checkbox UI to webview-ui/src/components/settings/SettingsView.tsx:
- Import the setting and its setter from ExtensionStateContext
- Add the VSCodeCheckbox component with the setting's state and onChange handler
- Add appropriate labels and description text
- Example:
```typescript
setMultisearchDiffEnabled(e.target.checked)}
>
Enable multi-search diff matching
```
5. Add the setting to handleSubmit in webview-ui/src/components/settings/SettingsView.tsx:
- Add a vscode.postMessage call to send the setting's value when clicking Save
- This step is critical for persistence - without it, the setting will not be saved when the user clicks Save
- Example:
```typescript
vscode.postMessage({ type: "multisearchDiffEnabled", bool: multisearchDiffEnabled })
```
6. Style Considerations:
- Use the VSCodeCheckbox component from @vscode/webview-ui-toolkit/react instead of HTML input elements
- Wrap each checkbox in a div element for proper spacing
- Use a span with className="font-medium" for the checkbox label inside the VSCodeCheckbox component
- Place the description in a separate div with className="text-vscode-descriptionForeground text-sm mt-1"
- Maintain consistent spacing between configuration options
- Example:
```typescript
```
## For Select/Dropdown Settings
1. Add the message type to src/shared/WebviewMessage.ts:
- Add the setting name to the WebviewMessage type's type union
- Example: `| "preferredLanguage"`
2. Add the setting to webview-ui/src/context/ExtensionStateContext.tsx:
- Add the setting to the ExtensionStateContextType interface
- Add the setter function to the interface
- Add the setting to the initial state in useState with a default value
- Add the setting to the contextValue object
- Example:
```typescript
interface ExtensionStateContextType {
preferredLanguage: string
setPreferredLanguage: (value: string) => void
}
```
3. Add the setting to src/core/webview/ClineProvider.ts:
- Add the setting name to the GlobalStateKey type union
- Add the setting to the Promise.all array in getState
- Add the setting to the return value in getState with a default value
- Add the setting to the destructured variables in getStateToPostToWebview
- Add the setting to the return value in getStateToPostToWebview
- This step is critical for UI display - without it, the setting will not be displayed in the UI
- Add a case in setWebviewMessageListener to handle the setting's message type
- Example:
```typescript
case "preferredLanguage":
await this.updateGlobalState("preferredLanguage", message.text)
await this.postStateToWebview()
break
```
4. Add the select UI to webview-ui/src/components/settings/SettingsView.tsx:
- Import the setting and its setter from ExtensionStateContext
- Add the select element with appropriate styling to match VSCode's theme
- Add options for the dropdown
- Add appropriate labels and description text
- Example:
```typescript
```
5. Add the setting to handleSubmit in webview-ui/src/components/settings/SettingsView.tsx:
- Add a vscode.postMessage call to send the setting's value when clicking Done
- Example:
```typescript
vscode.postMessage({ type: "preferredLanguage", text: preferredLanguage })
```
These steps ensure that:
- The setting's state is properly typed throughout the application
- The setting persists between sessions
- The setting's value is properly synchronized between the webview and extension
- The setting has a proper UI representation in the settings view
- Test coverage is maintained for the new setting
## Adding a New Configuration Item: Summary of Required Changes
To add a new configuration item to the system, the following changes are necessary:
1. **Feature-Specific Class** (if applicable)
- For settings that affect specific features (e.g., Terminal, Browser, etc.)
- Add a static property to store the value
- Add getter/setter methods to access and modify the value
2. **Schema Definition**
- Add the item to globalSettingsSchema in src/schemas/index.ts
- Add the item to globalSettingsRecord in src/schemas/index.ts
3. **Type Definitions**
- Add the item to src/exports/types.ts
- Add the item to src/exports/roo-code.d.ts
- Add the item to src/shared/ExtensionMessage.ts
- Add the item to src/shared/WebviewMessage.ts
4. **UI Component**
- Create or update a component in webview-ui/src/components/settings/
- Add appropriate slider/input controls with min/max/step values
- Ensure the props are passed correctly to the component in webview-ui/src/components/settings/SettingsView.tsx
- Update the component's props interface to include the new settings
5. **Translations**
- Add label and description in webview-ui/src/i18n/locales/en/settings.json
- Update all other languages
- If any language content is changed, synchronize all other languages with that change
- Translations must be performed within "translation" mode so change modes for that purpose
6. **State Management**
- Add the item to the destructuring in SettingsView.tsx
- Add the item to the handleSubmit function in webview-ui/src/components/settings/SettingsView.tsx
- Add the item to getStateToPostToWebview in src/core/webview/ClineProvider.ts
- Add the item to getState in src/core/webview/ClineProvider.ts with appropriate default values
- Add the item to the initialization in resolveWebviewView in src/core/webview/ClineProvider.ts
7. **Message Handling**
- Add a case for the item in src/core/webview/webviewMessageHandler.ts
8. **Implementation-Specific Logic**
- Implement any feature-specific behavior triggered by the setting
- Examples:
- Environment variables for terminal settings
- API configuration changes for provider settings
- UI behavior modifications for display settings
9. **Testing**
- Add test cases for the new settings in appropriate test files
- Verify settings persistence and state updates
10. **Ensuring Settings Persistence Across Reload**
To ensure settings persist across application reload, several key components must be properly configured:
1. **Initial State in ExtensionStateContextProvider**:
- Add the setting to the initial state in the useState call
- Example:
```typescript
const [state, setState] = useState({
// existing settings...
newSetting: false, // Default value for the new setting
})
```
2. **State Loading in ClineProvider**:
- Add the setting to the getState method to load it from storage
- Example:
```typescript
return {
// existing settings...
newSetting: stateValues.newSetting ?? false,
}
```
3. **State Initialization in resolveWebviewView**:
- Add the setting to the initialization in resolveWebviewView
- Example:
```typescript
this.getState().then(
({
// existing settings...
newSetting,
}) => {
// Initialize the setting with its stored value or default
FeatureClass.setNewSetting(newSetting ?? false)
},
)
```
4. **State Transmission to Webview**:
- Add the setting to the getStateToPostToWebview method
- Example:
```typescript
return {
// existing settings...
newSetting: newSetting ?? false,
}
```
5. **Setter Method in ExtensionStateContext**:
- Add the setter method to the contextValue object
- Example:
```typescript
const contextValue: ExtensionStateContextType = {
// existing properties and methods...
setNewSetting: (value) => setState((prevState) => ({ ...prevState, newSetting: value })),
}
```
11. **Debugging Settings Persistence Issues**
If a setting is not persisting across reload, check the following:
1. **Complete Chain of Persistence**:
- Verify that the setting is added to all required locations:
- globalSettingsSchema and globalSettingsRecord in src/schemas/index.ts
- Initial state in ExtensionStateContextProvider
- getState method in src/core/webview/ClineProvider.ts
- getStateToPostToWebview method in src/core/webview/ClineProvider.ts
- resolveWebviewView method in src/core/webview/ClineProvider.ts (if feature-specific)
- A break in any part of this chain can prevent persistence
2. **Default Values Consistency**:
- Ensure default values are consistent across all locations
- Inconsistent defaults can cause unexpected behavior
3. **Message Handling**:
- Confirm the src/core/webview/webviewMessageHandler.ts has a case for the setting
- Verify the message type matches what's sent from the UI
4. **UI Integration**:
- Check that the setting is included in the handleSubmit function in webview-ui/src/components/settings/SettingsView.tsx
- Ensure the UI component correctly updates the state
5. **Type Definitions**:
- Verify the setting is properly typed in all relevant interfaces
- Check for typos in property names across different files
6. **Storage Mechanism**:
- For complex settings, ensure proper serialization/deserialization
- Check that the setting is being correctly stored in VSCode's globalState
These checks help identify and resolve common issues with settings persistence.
12. **Advanced Troubleshooting: The Complete Settings Persistence Chain**
Settings persistence requires a complete chain of state management across multiple components. Understanding this chain is critical for both humans and AI to effectively troubleshoot persistence issues:
1. **Schema Definition (Entry Point)**:
- Settings must be properly defined in `globalSettingsSchema` and `globalSettingsRecord`
- Enum values should use proper zod schemas: `z.enum(["value1", "value2"])`
- Example:
```typescript
// In src/schemas/index.ts
export const globalSettingsSchema = z.object({
// Existing settings...
commandRiskLevel: z.enum(["readOnly", "reversibleChanges", "complexChanges"]).optional(),
})
const globalSettingsRecord: GlobalSettingsRecord = {
// Existing settings...
commandRiskLevel: undefined,
}
```
2. **UI Component (User Interaction)**:
- Must use consistent components (Select vs. select) with other similar settings
- Must use `setCachedStateField` for state updates, not direct state setting
- Must generate the correct message type through `vscode.postMessage`
- Example:
```tsx
// In a settings component
```
3. **Message Handler (State Saving)**:
- Must use correct message type in `src/core/webview/webviewMessageHandler.ts`
- Must use `updateGlobalState` with properly typed values
- Must call `postStateToWebview` after updates
- Example:
```typescript
// In src/core/webview/webviewMessageHandler.ts
case "commandRiskLevel":
await updateGlobalState(
"commandRiskLevel",
(message.text ?? "readOnly") as "readOnly" | "reversibleChanges" | "complexChanges"
)
await provider.postStateToWebview()
break
```
4. **State Retrieval (Reading State)**:
- In `getState`, state must be properly retrieved from stateValues
- In `getStateToPostToWebview`, the setting must be in the destructured parameters
- The setting must be included in the return value
- Use `contextProxy.getGlobalState` for direct access when needed
- Example:
```typescript
// In src/core/webview/ClineProvider.ts getStateToPostToWebview
const {
// Other state properties...
commandRiskLevel,
} = await this.getState()
return {
// Other state properties...
commandRiskLevel: commandRiskLevel ?? "readOnly",
}
```
5. **Debugging Strategies**:
- **Follow the State Flow**: Watch the setting's value at each step in the chain
- **Type Safety**: Ensure the same type is used throughout the chain
- **Component Consistency**: Use the same pattern as other working settings
- **Check Return Values**: Ensure the setting is included in all return objects
- **State vs. Configuration**: Understand when to use state vs. VSCode configuration
6. **Common Pitfalls**:
- **Type Mismatch**: Using string where an enum is expected
- **Chain Breaks**: Missing the setting in return objects
- **UI Inconsistency**: Using different component patterns
- **DefaultValue Issues**: Inconsistent default values across components
- **Missing Schema**: Not adding to schema or record definitions
Remember: A break at ANY point in this chain can cause persistence failures. When troubleshooting, systematically check each link in the chain to identify where the issue occurs.