├── README.md ├── SCRIPT_README.md ├── claude_complete_modification_guide.md ├── claude_hacked_instructions.md ├── claude_token_limits.md ├── context.md ├── hack_claude.py └── workbench-pretty.js /README.md: -------------------------------------------------------------------------------- 1 | # Comprehensive Guide to Claude 3.7 Customization in Cursor 2 | 3 | This document provides detailed instructions for modifying and optimizing various aspects of Claude 3.7 in Cursor, including token limits, thinking level, and UI styling. These modifications are purely client-side and do not require changes to the Anthropic API. 4 | 5 | ## 1. Increase Claude's Token Context Window 6 | 7 | ### Technical Background 8 | Claude's token context window is controlled by the `getEffectiveTokenLimit` function. By default, standard Claude models use a 30,000 token limit, while the Max variants use a 200,000 token limit. 9 | 10 | ### Steps to Increase Context Window 11 | 12 | #### Step 1: Locate the `getEffectiveTokenLimit` Function 13 | In the `workbench.desktop.main.js` file (usually at `/resources/app/out/vs/workbench/workbench.desktop.main.js`), search for: 14 | ```js 15 | async getEffectiveTokenLimit(e) { 16 | ``` 17 | 18 | #### Step 2: Modify the Function to Use Higher Limits 19 | Replace the original function with this modified version to set a 200,000 token limit: 20 | 21 | ```js 22 | async getEffectiveTokenLimit(e) { 23 | if(e.modelName && e.modelName.includes('claude-3.7')) return 200000; 24 | 25 | // Original function code below 26 | const n = e.modelName; 27 | if (!n) return 3e4; 28 | const r = `${n}_token_limit`; 29 | 30 | // Rest of the original function... 31 | } 32 | ``` 33 | 34 | For all models (not just Claude 3.7): 35 | ```js 36 | async getEffectiveTokenLimit(e) { 37 | return 200000; // Always use 200K limit for all models 38 | 39 | // Original function code will never run 40 | const n = e.modelName; 41 | // ... 42 | } 43 | ``` 44 | 45 | ## 2. Always Set Claude's Thinking Level to High 46 | 47 | ### Technical Background 48 | Claude's thinking level controls how much reasoning it shows during generation. The "high" level provides the most detailed thinking process. 49 | 50 | ### Steps to Set Thinking Level to High 51 | 52 | #### Step 1: Locate the `getModeThinkingLevel` Function 53 | In the `workbench.desktop.main.js` file, search for: 54 | ```js 55 | getModeThinkingLevel(e) { 56 | return this.getAllModes().find((n) => n.id === e)?.thinkingLevel ?? "none"; 57 | } 58 | ``` 59 | 60 | #### Step 2: Modify the Function to Always Return "high" 61 | Replace it with: 62 | ```js 63 | getModeThinkingLevel(e) { 64 | return "high"; 65 | } 66 | ``` 67 | 68 | #### Step 3: Verify the `getThinkingLevel` Function 69 | Make sure this function correctly maps "high" to the appropriate enum value. It should look like: 70 | ```js 71 | getThinkingLevel(e) { 72 | switch (e) { 73 | case "high": 74 | return tH.HIGH; 75 | case "medium": 76 | return tH.MEDIUM; 77 | default: 78 | return tH.UNSPECIFIED; 79 | } 80 | } 81 | ``` 82 | 83 | ## 3. Customize Claude 3.7 UI Styling (Rename & Restyle) 84 | 85 | ### Technical Background 86 | The UI display of Claude models is controlled by style objects that define how models appear in dropdowns and the chat interface. 87 | 88 | ### Steps to Customize Claude 3.7 Regular (Non-Max) 89 | 90 | #### Step 1: Locate the Claude 3.7 UI Definition 91 | Find where the regular Claude 3.7 model is styled by searching for: 92 | ```js 93 | a = { ...e, title: "claude-3.7-sonnet", id: r, _serializableTitle: () => "claude-3.7-sonnet" }, 94 | ``` 95 | 96 | #### Step 2: Modify the UI Component 97 | Replace with this code to add custom styling: 98 | ```js 99 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 gradient-text-high font-bold", _serializableTitle: () => "3.7 Hacked" }, 100 | ``` 101 | 102 | This will: 103 | - Add a "HACKED" subtitle 104 | - Apply the same gradient styling as the "MAX" version 105 | - Make the text bold 106 | - Show "3.7 Hacked" in dropdowns and model selection UI elements 107 | 108 | #### Alternative Styling Options 109 | 110 | If you want to use red text instead of the gradient: 111 | ```js 112 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 text-red-600 font-bold", _serializableTitle: () => "3.7 Hacked" }, 113 | ``` 114 | 115 | For animation effects (may not work in all Cursor versions): 116 | ```js 117 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 text-red-500 animate-pulse font-bold", _serializableTitle: () => "3.7 Hacked" }, 118 | ``` 119 | 120 | ## 4. Combined Modifications: Ultimate Claude Setup 121 | 122 | For the ultimate setup that combines all modifications, follow these steps in order: 123 | 124 | 1. First, create a backup of your `workbench.desktop.main.js` file 125 | 2. Apply the token limit modification to enable 200K context 126 | 3. Apply the thinking level modification to always use high-level thinking 127 | 4. Apply the UI customization to make Claude 3.7 stand out 128 | 129 | ### Example of All Modifications Together: 130 | 131 | ```js 132 | // 1. Modify getEffectiveTokenLimit 133 | async getEffectiveTokenLimit(e) { 134 | return 200000; // 200K token limit for all models 135 | 136 | // Original code below will be skipped 137 | const n = e.modelName; 138 | // ... 139 | } 140 | 141 | // 2. Modify getModeThinkingLevel 142 | getModeThinkingLevel(e) { 143 | return "high"; 144 | } 145 | 146 | // 3. Modify UI component 147 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 gradient-text-high font-bold", _serializableTitle: () => "3.7 Hacked" }, 148 | ``` 149 | 150 | ## How to Find Files After Cursor Updates 151 | 152 | If Cursor updates and file paths change, use these commands to locate the right files: 153 | 154 | ```bash 155 | # Find the workbench.desktop.main.js file 156 | find /path/to/cursor -name "workbench.desktop.main*.js" 157 | 158 | # Search for getEffectiveTokenLimit function 159 | grep -n "getEffectiveTokenLimit" [path-to-file] 160 | 161 | # Search for getModeThinkingLevel function 162 | grep -n "getModeThinkingLevel" [path-to-file] 163 | 164 | # Search for claude-3.7-sonnet styling 165 | grep -n "title: \"claude-3.7-sonnet\"" [path-to-file] 166 | ``` 167 | 168 | ## Automated Modification with Python 169 | 170 | For an automated approach, you can use the included Python tool in the `cursor_modifier` directory: 171 | 172 | 1. Run `python cursor_claude_modifier.py` or use the batch files (`run_modifier.bat` for Windows, `run_modifier.sh` for Linux/Mac) 173 | 2. The tool will: 174 | - Locate the Cursor installation 175 | - Find the relevant JavaScript files 176 | - Create backups of original files 177 | - Apply the selected modifications 178 | - Show you a diff of the changes before applying them 179 | 180 | ## Warning and Known Issues 181 | 182 | 1. **Updates Override Changes**: Cursor updates will likely overwrite these modifications. You'll need to reapply them after updates. 183 | 184 | 2. **No Server-Side Changes**: These modifications only affect the client-side code. The actual token usage is still controlled by Anthropic's API, so you may encounter server-side limitations. 185 | 186 | 3. **UI Limitations**: 187 | - Some UI modifications may not appear exactly as expected due to CSS interactions 188 | - The gradient styling may render differently in different themes 189 | - Animation effects may not work in all versions of Cursor 190 | 191 | 4. **API Key Requirements**: These modifications don't bypass any API key requirements. If you're using your own API key, costs are still determined by Anthropic's pricing. 192 | 193 | 5. **Thinking Level Impact**: Setting thinking level to "high" will make Claude show more of its reasoning process, which may increase token usage. 194 | 195 | ## Technical Implementation Details 196 | 197 | ### Token Limit Implementation 198 | - The token limit is controlled by the `getEffectiveTokenLimit` function 199 | - This function first checks a cache, then calls an API, and falls back to default limits 200 | - By modifying this function, we bypass the API call and directly set our preferred limit 201 | 202 | ### Thinking Level Implementation 203 | - The thinking level is controlled by the `getModeThinkingLevel` function 204 | - Thinking levels include "none" (default), "medium", and "high" 205 | - The `getThinkingLevel` function converts string values to enum constants used internally 206 | 207 | ### UI Styling Implementation 208 | - Model UI is controlled by style objects with properties like `title`, `subTitle`, `subTitleClass` 209 | - The `_serializableTitle` function controls how the model appears in dropdowns 210 | - CSS classes like `gradient-text-high` create the premium gradient effect seen in the MAX version 211 | 212 | Remember to make backups before making changes. These modifications affect only the local client and don't change Claude's actual capabilities or underlying API interactions. 213 | -------------------------------------------------------------------------------- /SCRIPT_README.md: -------------------------------------------------------------------------------- 1 | # Claude 3.7 Hack Tool 2 | 3 | A simple script to enhance Claude 3.7 in Cursor by: 4 | 5 | 1. **Increasing token limit** to 200,000 tokens 6 | 2. **Setting thinking level** to "high" for more detailed reasoning 7 | 3. **Adding custom UI styling** to distinguish the enhanced model 8 | 9 | ## How It Works 10 | 11 | The script uses precise string matching to find and modify specific functions: 12 | 13 | - **Token limit**: Uses multiple patterns and fallbacks to find `getEffectiveTokenLimit` function 14 | - **Thinking level**: Searches for `getModeThinkingLevel(e)` 15 | - **UI styling**: Searches for `_serializableTitle:()=>"claude-3.7-sonnet"}` 16 | 17 | This approach provides reliable matches across different Cursor versions, even when the code has been minified or slightly modified. 18 | 19 | ## Usage 20 | 21 | ### Basic Usage 22 | 23 | ```bash 24 | python hack_claude.py 25 | ``` 26 | 27 | The script automatically finds Cursor's workbench file and applies the modifications. 28 | 29 | ### Options 30 | 31 | ```bash 32 | python hack_claude.py --token-mode all_models --ui-style red 33 | ``` 34 | 35 | | Option | Values | Default | Description | 36 | |--------|--------|---------|-------------| 37 | | `--file`, `-f` | file path | (auto-detect) | Path to workbench.desktop.main.js | 38 | | `--token-mode`, `-t` | `claude37_only`, `all_models` | `claude37_only` | Apply token limit to which models | 39 | | `--ui-style`, `-u` | `gradient`, `red`, `animated` | `gradient` | UI style for the hacked model | 40 | | `--skip-backup`, `-s` | flag | False | Skip backup creation | 41 | 42 | ## Examples 43 | 44 | Modify only Claude 3.7 with animated styling: 45 | ```bash 46 | python hack_claude.py --ui-style animated 47 | ``` 48 | 49 | Apply the 200K limit to all models: 50 | ```bash 51 | python hack_claude.py --token-mode all_models 52 | ``` 53 | 54 | ## Notes 55 | 56 | - Creates backups before making changes 57 | - Changes are lost when Cursor updates 58 | - Client-side changes only - actual behavior still depends on Anthropic's API 59 | - If you encounter issues, try using a backup file with `--file path/to/backup.js` 60 | -------------------------------------------------------------------------------- /claude_complete_modification_guide.md: -------------------------------------------------------------------------------- 1 | # Comprehensive Guide to Claude 3.7 Customization in Cursor 2 | 3 | This document provides detailed instructions for modifying and optimizing various aspects of Claude 3.7 in Cursor, including token limits, thinking level, and UI styling. These modifications are purely client-side and do not require changes to the Anthropic API. 4 | 5 | ## 1. Increase Claude's Token Context Window 6 | 7 | ### Technical Background 8 | Claude's token context window is controlled by the `getEffectiveTokenLimit` function. By default, standard Claude models use a 30,000 token limit, while the Max variants use a 200,000 token limit. 9 | 10 | ### Steps to Increase Context Window 11 | 12 | #### Step 1: Locate the `getEffectiveTokenLimit` Function 13 | In the `workbench.desktop.main.js` file (usually at `/resources/app/out/vs/workbench/workbench.desktop.main.js`), search for: 14 | ```js 15 | async getEffectiveTokenLimit(e) { 16 | ``` 17 | 18 | #### Step 2: Modify the Function to Use Higher Limits 19 | Replace the original function with this modified version to set a 200,000 token limit: 20 | 21 | ```js 22 | async getEffectiveTokenLimit(e) { 23 | if(e.modelName && e.modelName.includes('claude-3.7')) return 200000; 24 | 25 | // Original function code below 26 | const n = e.modelName; 27 | if (!n) return 3e4; 28 | const r = `${n}_token_limit`; 29 | 30 | // Rest of the original function... 31 | } 32 | ``` 33 | 34 | For all models (not just Claude 3.7): 35 | ```js 36 | async getEffectiveTokenLimit(e) { 37 | return 200000; // Always use 200K limit for all models 38 | 39 | // Original function code will never run 40 | const n = e.modelName; 41 | // ... 42 | } 43 | ``` 44 | 45 | ## 2. Always Set Claude's Thinking Level to High 46 | 47 | ### Technical Background 48 | Claude's thinking level controls how much reasoning it shows during generation. The "high" level provides the most detailed thinking process. 49 | 50 | ### Steps to Set Thinking Level to High 51 | 52 | #### Step 1: Locate the `getModeThinkingLevel` Function 53 | In the `workbench.desktop.main.js` file, search for: 54 | ```js 55 | getModeThinkingLevel(e) { 56 | return this.getAllModes().find((n) => n.id === e)?.thinkingLevel ?? "none"; 57 | } 58 | ``` 59 | 60 | #### Step 2: Modify the Function to Always Return "high" 61 | Replace it with: 62 | ```js 63 | getModeThinkingLevel(e) { 64 | return "high"; 65 | } 66 | ``` 67 | 68 | #### Step 3: Verify the `getThinkingLevel` Function 69 | Make sure this function correctly maps "high" to the appropriate enum value. It should look like: 70 | ```js 71 | getThinkingLevel(e) { 72 | switch (e) { 73 | case "high": 74 | return tH.HIGH; 75 | case "medium": 76 | return tH.MEDIUM; 77 | default: 78 | return tH.UNSPECIFIED; 79 | } 80 | } 81 | ``` 82 | 83 | ## 3. Customize Claude 3.7 UI Styling (Rename & Restyle) 84 | 85 | ### Technical Background 86 | The UI display of Claude models is controlled by style objects that define how models appear in dropdowns and the chat interface. 87 | 88 | ### Steps to Customize Claude 3.7 Regular (Non-Max) 89 | 90 | #### Step 1: Locate the Claude 3.7 UI Definition 91 | Find where the regular Claude 3.7 model is styled by searching for: 92 | ```js 93 | a = { ...e, title: "claude-3.7-sonnet", id: r, _serializableTitle: () => "claude-3.7-sonnet" }, 94 | ``` 95 | 96 | #### Step 2: Modify the UI Component 97 | Replace with this code to add custom styling: 98 | ```js 99 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 gradient-text-high font-bold", _serializableTitle: () => "3.7 Hacked" }, 100 | ``` 101 | 102 | This will: 103 | - Add a "HACKED" subtitle 104 | - Apply the same gradient styling as the "MAX" version 105 | - Make the text bold 106 | - Show "3.7 Hacked" in dropdowns and model selection UI elements 107 | 108 | #### Alternative Styling Options 109 | 110 | If you want to use red text instead of the gradient: 111 | ```js 112 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 text-red-600 font-bold", _serializableTitle: () => "3.7 Hacked" }, 113 | ``` 114 | 115 | For animation effects (may not work in all Cursor versions): 116 | ```js 117 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 text-red-500 animate-pulse font-bold", _serializableTitle: () => "3.7 Hacked" }, 118 | ``` 119 | 120 | ## 4. Combined Modifications: Ultimate Claude Setup 121 | 122 | For the ultimate setup that combines all modifications, follow these steps in order: 123 | 124 | 1. First, create a backup of your `workbench.desktop.main.js` file 125 | 2. Apply the token limit modification to enable 200K context 126 | 3. Apply the thinking level modification to always use high-level thinking 127 | 4. Apply the UI customization to make Claude 3.7 stand out 128 | 129 | ### Example of All Modifications Together: 130 | 131 | ```js 132 | // 1. Modify getEffectiveTokenLimit 133 | async getEffectiveTokenLimit(e) { 134 | return 200000; // 200K token limit for all models 135 | 136 | // Original code below will be skipped 137 | const n = e.modelName; 138 | // ... 139 | } 140 | 141 | // 2. Modify getModeThinkingLevel 142 | getModeThinkingLevel(e) { 143 | return "high"; 144 | } 145 | 146 | // 3. Modify UI component 147 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 gradient-text-high font-bold", _serializableTitle: () => "3.7 Hacked" }, 148 | ``` 149 | 150 | ## How to Find Files After Cursor Updates 151 | 152 | If Cursor updates and file paths change, use these commands to locate the right files: 153 | 154 | ```bash 155 | # Find the workbench.desktop.main.js file 156 | find /path/to/cursor -name "workbench.desktop.main*.js" 157 | 158 | # Search for getEffectiveTokenLimit function 159 | grep -n "getEffectiveTokenLimit" [path-to-file] 160 | 161 | # Search for getModeThinkingLevel function 162 | grep -n "getModeThinkingLevel" [path-to-file] 163 | 164 | # Search for claude-3.7-sonnet styling 165 | grep -n "title: \"claude-3.7-sonnet\"" [path-to-file] 166 | ``` 167 | 168 | ## Automated Modification with Python 169 | 170 | For an automated approach, you can use the included Python tool in the `cursor_modifier` directory: 171 | 172 | 1. Run `python cursor_claude_modifier.py` or use the batch files (`run_modifier.bat` for Windows, `run_modifier.sh` for Linux/Mac) 173 | 2. The tool will: 174 | - Locate the Cursor installation 175 | - Find the relevant JavaScript files 176 | - Create backups of original files 177 | - Apply the selected modifications 178 | - Show you a diff of the changes before applying them 179 | 180 | ## Warning and Known Issues 181 | 182 | 1. **Updates Override Changes**: Cursor updates will likely overwrite these modifications. You'll need to reapply them after updates. 183 | 184 | 2. **No Server-Side Changes**: These modifications only affect the client-side code. The actual token usage is still controlled by Anthropic's API, so you may encounter server-side limitations. 185 | 186 | 3. **UI Limitations**: 187 | - Some UI modifications may not appear exactly as expected due to CSS interactions 188 | - The gradient styling may render differently in different themes 189 | - Animation effects may not work in all versions of Cursor 190 | 191 | 4. **API Key Requirements**: These modifications don't bypass any API key requirements. If you're using your own API key, costs are still determined by Anthropic's pricing. 192 | 193 | 5. **Thinking Level Impact**: Setting thinking level to "high" will make Claude show more of its reasoning process, which may increase token usage. 194 | 195 | ## Technical Implementation Details 196 | 197 | ### Token Limit Implementation 198 | - The token limit is controlled by the `getEffectiveTokenLimit` function 199 | - This function first checks a cache, then calls an API, and falls back to default limits 200 | - By modifying this function, we bypass the API call and directly set our preferred limit 201 | 202 | ### Thinking Level Implementation 203 | - The thinking level is controlled by the `getModeThinkingLevel` function 204 | - Thinking levels include "none" (default), "medium", and "high" 205 | - The `getThinkingLevel` function converts string values to enum constants used internally 206 | 207 | ### UI Styling Implementation 208 | - Model UI is controlled by style objects with properties like `title`, `subTitle`, `subTitleClass` 209 | - The `_serializableTitle` function controls how the model appears in dropdowns 210 | - CSS classes like `gradient-text-high` create the premium gradient effect seen in the MAX version 211 | 212 | Remember to make backups before making changes. These modifications affect only the local client and don't change Claude's actual capabilities or underlying API interactions. -------------------------------------------------------------------------------- /claude_hacked_instructions.md: -------------------------------------------------------------------------------- 1 | # Claude Customization Instructions 2 | 3 | This document provides instructions for customizing Claude 3.7 in Cursor. These modifications are UI-only and don't affect functionality. 4 | 5 | ## 1. Always Set Claude's Thinking Level to High 6 | 7 | ### Step 1: Locate the getModeThinkingLevel Function 8 | In the `workbench.desktop.main.js` file, locate the `getModeThinkingLevel` function by searching for: 9 | ```js 10 | getModeThinkingLevel(e) { 11 | return this.getAllModes().find((n) => n.id === e)?.thinkingLevel ?? "none"; 12 | } 13 | ``` 14 | 15 | ### Step 2: Replace with Always High 16 | Replace it with: 17 | ```js 18 | getModeThinkingLevel(e) { 19 | return "high"; 20 | } 21 | ``` 22 | 23 | ## 2. Make Claude 3.7 Regular Appear as "3.7 Hacked" with Red Styling 24 | 25 | ### Step 1: Locate the UI Definition 26 | Find where the Claude 3.7 regular model is styled. Search for: 27 | ```js 28 | a = { ...e, title: "claude-3.7-sonnet", id: r, _serializableTitle: () => "claude-3.7-sonnet" }, 29 | ``` 30 | 31 | ### Step 2: Modify the UI Component 32 | Replace with: 33 | ```js 34 | a = { ...e, title: "claude-3.7-sonnet", id: r, subTitle: "HACKED", subTitleClass: "!opacity-100 text-red-500 animate-pulse font-bold", _serializableTitle: () => "3.7 Hacked" }, 35 | ``` 36 | 37 | If the animation doesn't work or only the subtitle shows, try these alternative solutions: 38 | 39 | ### Option 1: Use a Custom Subtitle Element 40 | Look for code that handles the MAX version and modify the regular version similarly: 41 | ```js 42 | a = { 43 | ...e, 44 | title: "claude-3.7-sonnet", 45 | id: r, 46 | subTitle: "HACKED", 47 | subTitleClass: "!opacity-100 text-red-600 font-bold", 48 | customSubTitle: (() => { 49 | var elem = document.createElement('span'); 50 | elem.textContent = "HACKED"; 51 | elem.style.color = "red"; 52 | elem.style.animation = "pulse 2s infinite"; 53 | elem.style.fontWeight = "bold"; 54 | return elem; 55 | })(), 56 | _serializableTitle: () => "3.7 Hacked" 57 | }, 58 | ``` 59 | 60 | ### Option 2: Add a CSS Keyframe Animation 61 | If your custom animation doesn't work, also add this CSS somewhere in the page: 62 | ```css 63 | @keyframes pulse { 64 | 0% { opacity: 0.6; } 65 | 50% { opacity: 1; } 66 | 100% { opacity: 0.6; } 67 | } 68 | ``` 69 | 70 | ### Option 3: Use Gradient Text Like MAX 71 | If red text doesn't show up, use the same gradient approach as MAX but with red tones: 72 | ```js 73 | a = { 74 | ...e, 75 | title: "claude-3.7-sonnet", 76 | id: r, 77 | subTitle: "HACKED", 78 | subTitleClass: "!opacity-100 gradient-text-high font-bold", 79 | _serializableTitle: () => "3.7 Hacked" 80 | }, 81 | ``` 82 | 83 | ## How to Find Files After Updates 84 | 85 | If Cursor updates and file paths change, use these commands to locate the right files: 86 | 87 | ```bash 88 | # Find the workbench.desktop.main.js file 89 | find /mnt/c/Users/aleja/AppData/Local/Programs/cursor -name "workbench.desktop.main*.js" 90 | 91 | # Search for getModeThinkingLevel function 92 | grep -n "getModeThinkingLevel" [path-to-file] 93 | 94 | # Search for claude-3.7-sonnet styling 95 | grep -n "title: \"claude-3.7-sonnet\"" [path-to-file] 96 | ``` 97 | 98 | Remember to make backups before making changes. These modifications only affect the UI and don't change Claude's functionality. -------------------------------------------------------------------------------- /claude_token_limits.md: -------------------------------------------------------------------------------- 1 | # Claude 3.7 Token Limits in Cursor 2 | 3 | This document explains how token limits for Claude 3.7 models are handled in Cursor, where the relevant code is located, and how to modify these limits if needed. 4 | 5 | ## Token Limit Implementation Overview 6 | 7 | ```mermaid 8 | flowchart TD 9 | A[User starts chat with Claude] --> B{Is model limit cached?} 10 | B -->|Yes| C[Use cached token limit] 11 | B -->|No| D[Call getEffectiveTokenLimit API] 12 | D --> E[Cache result for 24 hours] 13 | E --> F[Apply token limit] 14 | 15 | G[User sends message] --> H[Calculate token count] 16 | H --> I{Token count > limit?} 17 | I -->|Yes| J[Show warning or error] 18 | I -->|No| K[Process normally] 19 | ``` 20 | 21 | ## Key Files and Locations 22 | 23 | ### Main Files 24 | 25 | ```mermaid 26 | flowchart LR 27 | A[workbench.desktop.main.js] --> B[Token limit UI warnings] 28 | A --> C[Default fallback limits] 29 | A --> D[Token counting logic] 30 | 31 | E[extensionHostProcess.js] --> F[API definitions] 32 | E --> G[Model metadata] 33 | 34 | H[extensionHostWorkerMain.js] --> I[Worker process limits] 35 | ``` 36 | 37 | ### Critical Code Sections 38 | 39 | 1. **Default Token Limit**: 40 | - **File**: `resources/app/out/vs/workbench/workbench.desktop.main.js` (line ~2586) 41 | - **Description**: Sets default context token limit to 30,000 tokens 42 | 43 | 2. **Token Limit API**: 44 | - **File**: `resources/app/out/vs/workbench/workbench.desktop.main.js` (line ~612) 45 | - **Description**: Contains the `getEffectiveTokenLimit` function 46 | 47 | 3. **Claude Model Definitions**: 48 | - **File**: `resources/app/out/vs/workbench/workbench.desktop.main.js` (line ~2587-2589) 49 | - **Description**: Contains references to Claude 3.7 models and variants 50 | 51 | 4. **Model Response Handlers**: 52 | - **File**: `resources/app/out/vs/workbench/api/node/extensionHostProcess.js` (line ~139) 53 | - **Description**: Handles model metadata including token limits 54 | 55 | ## Claude 3.7 Regular vs. Max: Context Window Differences 56 | 57 | The code analysis reveals that the primary difference between regular Claude 3.7 Sonnet and the "Max" variants is the context window size. This is intentionally configured in the application: 58 | 59 | ```mermaid 60 | flowchart TD 61 | A[Claude 3.7 Models] --> B{Max Variant?} 62 | B -->|No| C[Standard Context Window] 63 | B -->|Yes| D[Large 200K Context Window] 64 | 65 | D --> E[Special flag: isLongContextOnly] 66 | E --> F[Higher getEffectiveTokenLimit value] 67 | ``` 68 | 69 | ### Key Evidence from Codebase 70 | 71 | 1. **Model Configuration Flags**: 72 | - The code at `resources/app/out/vs/workbench/workbench.desktop.main.js` (~line 572) shows other Claude models with 200K context using the `isLongContextOnly` flag: 73 | ```javascript 74 | {name:"claude-3-5-sonnet-200k", defaultOn:!0, isLongContextOnly:!0, supportsAgent:!0} 75 | ``` 76 | 77 | 2. **Context Window Access Control**: 78 | - In `workbench.desktop.main.js` (~line 74), there's a reference to `longContextOpenAIModel:"claude-3-5-sonnet-200k"`, showing that some Claude models are specifically flagged for long context 79 | 80 | 3. **Token Limit Resolution Flow**: 81 | - The `getEffectiveTokenLimit` function (line ~612) determines the token limit for a model by: 82 | 1. Checking a cache first 83 | 2. If not cached, calling the server API 84 | 3. Falling back to 200,000 tokens if the API fails 85 | - This system allows for dynamic configuration of token limits for different models without hardcoding them 86 | 87 | 4. **No Hard-Coded Distinction**: 88 | - There's no explicit code setting different token limits for `claude-3.7-sonnet` vs. `claude-3.7-sonnet-max` in the client 89 | - Instead, the `getEffectiveTokenLimit` API call retrieves these limits from the server 90 | 91 | ### How the "Max" Variants Get Higher Limits 92 | 93 | Based on the codebase patterns, when the app calls `getEffectiveTokenLimit` for a "Max" variant: 94 | 95 | 1. The server recognizes the model as premium 96 | 2. The server returns a higher token limit value (likely 200K) 97 | 3. The client stores this value in cache for 24 hours 98 | 4. All subsequent token limit checks use this cached higher value 99 | 100 | The regular Claude 3.7 variant follows the same pattern but receives a lower token limit from the server. 101 | 102 | ### Server-Side Control 103 | 104 | The actual token limit values are determined server-side, not in the client code. This allows Cursor to: 105 | 106 | 1. Update token limits without client changes 107 | 2. Configure different limits for different user tiers 108 | 3. Apply model-specific restrictions 109 | 4. Handle API-level token limit enforcement 110 | 111 | ## How to Modify Claude 3.7 Max Limits 112 | 113 | To give regular Claude 3.7 access to the same 200K context window as the Max variant, you would need to: 114 | 115 | 1. **Server-side change (ideal)**: Modify the server API to return the same token limit for regular Claude 3.7 as it does for the Max variant 116 | 117 | 2. **Client-side hack**: 118 | ```javascript 119 | // Find the getEffectiveTokenLimit function in workbench.desktop.main.js (~line 612) 120 | async getEffectiveTokenLimit(e) { 121 | const n = e.modelName; 122 | // Add this condition to override for Claude 3.7 123 | if (n === "claude-3.7-sonnet") { 124 | return 200000; // Same limit as Max 125 | } 126 | // Rest of the original function... 127 | } 128 | ``` 129 | 130 | 3. **Cache manipulation**: Another approach would be to manipulate the client-side token limit cache to always return the Max limit value for the regular variant. 131 | 132 | ## Modifying Token Limits 133 | 134 | ### Option 1: Override Default Fallback Limit 135 | 136 | ```mermaid 137 | flowchart LR 138 | A[Find default limit] --> B[Modify hard-coded value] 139 | B --> C[Rebuild application] 140 | ``` 141 | 142 | To increase the default fallback limit (used when the server doesn't provide a specific value): 143 | 144 | 1. Locate the line in `workbench.desktop.main.js` where the default limit is set (~line 2586) 145 | 2. Change `3e4` (30,000) to your desired value 146 | 3. Rebuild the application 147 | 148 | ### Option 2: Modify Server Response 149 | 150 | ```mermaid 151 | flowchart LR 152 | A[Intercept API response] --> B[Modify token limit value] 153 | B --> C[Return modified response] 154 | ``` 155 | 156 | If you have access to the server implementation: 157 | 158 | 1. Find the server-side implementation of `getEffectiveTokenLimit` 159 | 2. Adjust the returned token limit for Claude 3.7 models 160 | 3. Deploy the server changes 161 | 162 | ### Option 3: Client-Side Cache Override 163 | 164 | ```mermaid 165 | flowchart LR 166 | A[Locate token limit cache] --> B[Inject custom values] 167 | B --> C[Ensure cache persistence] 168 | ``` 169 | 170 | To override the client-side cache: 171 | 172 | 1. Find the token limit cache storage in `workbench.desktop.main.js` (~line 612) 173 | 2. Modify how the application stores or retrieves these values 174 | 3. Ensure your changes persist across application restarts 175 | 176 | ## Claude 3.7 Model Variants 177 | 178 | ```mermaid 179 | flowchart TD 180 | A[Claude 3.7 Sonnet Models] --> B[claude-3.7-sonnet] 181 | A --> C[claude-3.7-sonnet-max] 182 | A --> D[claude-3.7-sonnet-thinking] 183 | A --> E[claude-3.7-sonnet-thinking-max] 184 | 185 | B -->|Base model| F[Standard token limit] 186 | C -->|Max version| G[Potentially higher limit] 187 | D -->|Thinking version| H[Similar to base model] 188 | E -->|Thinking + Max| I[Highest potential limit] 189 | ``` 190 | 191 | ## Differences Between Claude 3.7 Variants 192 | 193 | Based on code analysis from the Cursor codebase, here are the key differences between Claude 3.7 variants: 194 | 195 | ### 1. Standard vs. Max Versions 196 | 197 | ```mermaid 198 | flowchart LR 199 | A[Claude 3.7 Standard] --> B[Base limits] 200 | A --> C[Default pricing] 201 | 202 | D[Claude 3.7 Max] --> E[Higher token limits] 203 | D --> F[Premium pricing] 204 | D --> G[Advanced capabilities] 205 | ``` 206 | 207 | The codebase reveals: 208 | 209 | - **Max vs. Standard**: The code at `workbench.desktop.main.js` (~line 2587-2589) shows "Max" variants have special UI treatments with gradient styling, suggesting premium status 210 | - **Visual Indicators**: Max models use a `"continuous-gradient-container gradient-high"` CSS class for visual distinction 211 | - **Different Default Usage**: The background composer model defaults to "claude-3.7-sonnet-thinking-max" (~line 572), suggesting this is considered the most capable variant 212 | 213 | ### 2. Regular vs. Thinking Modes 214 | 215 | ```mermaid 216 | flowchart TB 217 | A[Regular Mode] --> B[Standard processing] 218 | A --> C[Focused on final answers] 219 | 220 | D[Thinking Mode] --> E[Shows reasoning process] 221 | D --> F[Thinking level configurable] 222 | D --> G[Supports agent-based workflows] 223 | ``` 224 | 225 | From the codebase: 226 | 227 | - **Thinking Level Configuration**: `getModeThinkingLevel` function (~line 592) indicates thinking modes can be configured with different levels: "none", "medium", or "high" 228 | - **Thinking Time Tracking**: The app tracks and displays thinking time metrics (~line 2295) 229 | - **UI for Thinking**: There's dedicated UI for thinking states: "Planning next moves" vs. "Thought for X seconds" vs. "Stopped thinking" 230 | - **Thinking Mode Toggle**: Code (~line 2788) shows direct mode conversion between regular and thinking modes: 231 | ```javascript 232 | function Ut(qt){ 233 | return qt==="claude-3.7-sonnet"?"claude-3.7-sonnet-thinking": 234 | qt==="claude-3.7-sonnet-max"?"claude-3.7-sonnet-thinking-max": 235 | null 236 | } 237 | ``` 238 | 239 | ### 3. Configuration and Agent Support 240 | 241 | ```mermaid 242 | flowchart TD 243 | A[Model Configuration] --> B{Supports Agents?} 244 | B -->|Yes| C[claude-3.7-sonnet-thinking-max] 245 | B -->|Yes| D[claude-3.7-sonnet-thinking] 246 | B -->|Limited| E[claude-3.7-sonnet] 247 | B -->|Limited| F[claude-3.7-sonnet-max] 248 | ``` 249 | 250 | Key findings: 251 | 252 | - **Agent Support**: The `doesModelSupportAgent` function (~line 2007) is used to check if a model supports agent capabilities 253 | - **Tool Use**: The code suggests that thinking variants may have better integration with tools and agents 254 | - **Background Processing**: Max variants, especially "claude-3.7-sonnet-thinking-max", are used for background processing, indicating they may have better performance for complex tasks 255 | 256 | ### 4. Default Selection Logic 257 | 258 | The code at `workbench.desktop.main.js` (~line 2587) shows how model defaults are managed: 259 | 260 | ```javascript 261 | c7s = (i, e, t, s, n) => { 262 | if (i) 263 | if (e) 264 | if (i === "claude-3.7-sonnet") 265 | t("claude-3.7-sonnet-thinking"); 266 | else if (i === "claude-3.7-sonnet-max") 267 | t("claude-3.7-sonnet-thinking-max"); 268 | // ... other models 269 | else if (i === "claude-3.7-sonnet-thinking") 270 | t("claude-3.7-sonnet"); 271 | else if (i === "claude-3.7-sonnet-thinking-max") 272 | t("claude-3.7-sonnet-max"); 273 | // ... other logic 274 | } 275 | ``` 276 | 277 | This logic shows the close relationship between standard and thinking variants, with easy toggling between them. 278 | 279 | ## Warning and Error Handling 280 | 281 | ```mermaid 282 | sequenceDiagram 283 | participant User 284 | participant UI as Cursor UI 285 | participant API as Cursor API 286 | participant Claude as Claude Model 287 | 288 | User->>UI: Types message 289 | UI->>UI: Calculate token count 290 | UI->>UI: Check against limit 291 | alt Token count > limit 292 | UI->>User: Show warning 293 | User->>UI: Send anyway 294 | UI->>API: Submit with token count 295 | API->>Claude: Forward request 296 | Claude->>API: MAX_TOKENS error 297 | API->>UI: Display error 298 | else Token count <= limit 299 | UI->>API: Submit normally 300 | API->>Claude: Forward request 301 | Claude->>API: Process successfully 302 | API->>UI: Return response 303 | UI->>User: Display response 304 | end 305 | ``` 306 | 307 | ## Token Costs and Pricing 308 | 309 | While the exact pricing isn't hardcoded in the client code, there are indications of cost differences: 310 | 311 | 1. **Thinking Modes Cost Tracking**: The code tracks both `processedTokens` and `thinkingTokens` separately, along with their associated costs (`processedCost` and `thinkingCost`) 312 | 313 | 2. **Max Variants Premium Status**: The UI treatment of Max variants (with gradient styling) suggests they are premium offerings 314 | 315 | 3. **API Key Requirements**: There are references to Claude API keys, suggesting some models may require specific authentication or be available at different pricing tiers 316 | 317 | ## Technical Implementation Notes 318 | 319 | - Token limits are dynamically fetched from the server to allow for updates without client changes 320 | - The client caches these limits for 24 hours (864e5 milliseconds) 321 | - If the server request fails, a default of 200,000 tokens is used 322 | - The UI displays warnings when approaching the token limit 323 | - The system includes specific handling for MAX_TOKENS errors 324 | - Each model variant may have different token limits 325 | 326 | ## Claude 3.7 API Integration and Tool Usage 327 | 328 | Based on analysis of the codebase, here's how Cursor integrates with Claude 3.7 APIs and implements tool usage: 329 | 330 | ```mermaid 331 | sequenceDiagram 332 | participant User 333 | participant Renderer as Renderer Process 334 | participant ExtHost as Extension Host Process 335 | participant API as Cursor API Servers 336 | participant Claude as Anthropic API 337 | 338 | User->>Renderer: Enters request with tool context 339 | Renderer->>ExtHost: IPC message with request 340 | ExtHost->>API: Forward request to API server 341 | API->>Claude: Format request for Anthropic 342 | Claude->>API: Stream response with tool calls 343 | API->>ExtHost: Forward tool call requests 344 | ExtHost->>ExtHost: Execute tool 345 | ExtHost->>API: Send tool results back 346 | API->>Claude: Continue with tool results 347 | Claude->>API: Complete response 348 | API->>ExtHost: Forward final response 349 | ExtHost->>Renderer: Render result to user 350 | Renderer->>User: Display response and tool outputs 351 | ``` 352 | 353 | ### API Endpoints and Communication 354 | 355 | 1. **Server Endpoints**: 356 | - Primary API endpoints: `https://api2.cursor.sh`, `https://api3.cursor.sh`, and `https://api4.cursor.sh` 357 | - These servers act as proxies to Anthropic's API at `https://api.anthropic.com/v1/messages` 358 | 359 | 2. **Process Communication**: 360 | - Cursor uses a multi-process architecture based on Electron 361 | - Inter-Process Communication (IPC) connects the Renderer process and Extension Host process 362 | - The Extension Host handles direct communication with Claude via API servers 363 | 364 | ### Tool Integration Framework 365 | 366 | 1. **Tool Definition System**: 367 | - Tools are defined using the VSCode API extension interface 368 | - Each tool has a schema, name, and invoke function 369 | - Defined in `vscode.d.ts` with interfaces like `LanguageModelTool` and `LanguageModelToolCallPart` 370 | 371 | 2. **Tool Call Processing**: 372 | - When Claude makes a tool call, it returns a `LanguageModelToolCallPart` in the response stream 373 | - The Extension Host process executes the tool using `invokeTool` 374 | - Results are returned as `LanguageModelToolResultPart` objects 375 | - Tool execution can be synchronous or asynchronous 376 | 377 | 3. **Tool Types Available**: 378 | - **File System Tools**: Reading, writing, and navigating files 379 | - **Search Tools**: Code search, file search, and grep functionality 380 | - **Terminal Command Tools**: Executing shell commands 381 | - **Web Search Tools**: External web search integration 382 | 383 | ### Claude Request Structure 384 | 385 | Cursor formats requests to Claude using the Anthropic API format: 386 | 387 | ```javascript 388 | { 389 | messages: [ 390 | { role: "user", content: [{ type: "text", text: userMessage }] }, 391 | // Previous messages in conversation 392 | ], 393 | model: "claude-3.7-sonnet", // Or variant 394 | max_tokens: tokenLimit, // From getEffectiveTokenLimit 395 | system: systemPrompt, // Contains Cursor-specific instructions 396 | tools: [ 397 | // Tool definitions based on available tools 398 | { 399 | name: "toolName", 400 | description: "Tool description", 401 | input_schema: { /* JSON schema */ }, 402 | } 403 | ] 404 | } 405 | ``` 406 | 407 | ### Error Handling and Retry Logic 408 | 409 | 1. **Token Limit Errors**: 410 | - Code includes specific handling for `CLAUDE_IMAGE_TOO_LARGE` (error code 31) 411 | - MAX_TOKENS errors trigger UI warnings and suggestions 412 | 413 | 2. **API Communication Errors**: 414 | - Connection failures are handled with retry logic 415 | - Error codes are mapped to user-friendly messages 416 | - Custom fallbacks for common failure scenarios 417 | 418 | ### Personal API Key Integration 419 | 420 | 1. **Key Management**: 421 | - Users can provide their own Anthropic API keys through the `useClaudeKey` setting 422 | - Keys are stored securely using the application storage service 423 | - Sample API key usage appears in code snippets for both PowerShell and curl 424 | 425 | 2. **Key-based Features**: 426 | - When a personal key is used, different error handling may apply 427 | - Premium features may be available based on the user's Anthropic account tier 428 | 429 | This comprehensive analysis shows how Cursor integrates Claude 3.7 models using a sophisticated multi-process architecture, with detailed tool support and robust error handling capabilities. -------------------------------------------------------------------------------- /context.md: -------------------------------------------------------------------------------- 1 | # Cursor IDE Codebase Context and Data Flow 2 | 3 | This document provides a granular analysis of the Cursor IDE codebase, focusing on component interactions, data flow, and specifically how contextual information is managed and passed between different parts of the system. We'll use Mermaid diagrams to illustrate these relationships. 4 | 5 | ## 1. High-Level Component Interaction 6 | 7 | As established in the main documentation, Cursor uses a multi-process architecture based on Electron. Here's a refined view of the core component interactions: 8 | 9 | ```mermaid 10 | graph LR 11 | subgraph Main_Process [Main Process] 12 | A[Application Lifecycle] 13 | B[Window Management] 14 | C[Global Settings] 15 | D[IPC Handler] 16 | end 17 | 18 | subgraph Renderer_Processes [Renderer Processes] 19 | E[Core Editor] 20 | F[UI Rendering] 21 | G[Command Execution] 22 | H[Webviews] 23 | I[IPC Client] 24 | end 25 | 26 | subgraph Extension_Host_Processes [Extension Host Processes] 27 | J[Extension Manager] 28 | K[Extension Execution] 29 | L[IPC Client/Server] 30 | end 31 | 32 | subgraph Shared_Process [Shared Process] 33 | M[Shared Tasks] 34 | N[IPC Handler] 35 | end 36 | 37 | subgraph Worker_Processes [Worker Processes] 38 | O[Background Tasks] 39 | end 40 | 41 | subgraph Pty_Host [Pty Host] 42 | P[Terminal] 43 | end 44 | 45 | subgraph File_Watcher [File Watcher] 46 | Q[File System Monitoring] 47 | end 48 | 49 | Main_Process -- IPC --> Renderer_Processes 50 | Main_Process -- IPC --> Extension_Host_Processes 51 | Main_Process -- IPC --> Shared_Process 52 | Main_Process -- IPC --> Worker_Processes 53 | Main_Process -- IPC --> Pty_Host 54 | Main_Process -- IPC --> File_Watcher 55 | 56 | Renderer_Processes -- IPC --> Extension_Host_Processes 57 | Renderer_Processes -- postMessage --> H 58 | H -- postMessage --> Renderer_Processes 59 | Extension_Host_Processes -- IPC --> Renderer_Processes 60 | Extension_Host_Processes -- IPC/Function Calls --> Worker_Processes 61 | 62 | Shared_Process -- IPC --> Renderer_Processes 63 | Shared_Process -- IPC --> Extension_Host_Processes 64 | 65 | File_Watcher -- IPC --> Main_Process 66 | File_Watcher -- IPC --> Renderer_Processes 67 | Pty_Host -- IPC --> Renderer_Processes 68 | 69 | style Main_Process fill:#ccf,stroke:#333,stroke-width:2px 70 | style Renderer_Processes fill:#fcf,stroke:#333,stroke-width:2px 71 | style Extension_Host_Processes fill:#cff,stroke:#333,stroke-width:2px 72 | style Shared_Process fill:#fcc,stroke:#333,stroke-width:2px 73 | style Worker_Processes fill:#ffc,stroke:#333,stroke-width:2px 74 | style Pty_Host fill:#ccf,stroke:#333,stroke-width:2px 75 | style File_Watcher fill:#fcf,stroke:#333,stroke-width:2px 76 | 77 | ``` 78 | 79 | **Key Observations:** 80 | 81 | * **Central Role of IPC:** Inter-Process Communication (IPC) is the backbone of communication between all major processes. 82 | * **Webview Isolation:** Webviews communicate with the renderer process (and indirectly with the extension host) via `postMessage`, maintaining a security boundary. 83 | * **Extension Host Isolation:** Extensions run in separate processes, communicating via IPC with the renderer and potentially worker processes. 84 | 85 | ## 2. Context Passing Mechanisms 86 | 87 | Cursor, like VS Code, relies on several mechanisms to manage and pass context: 88 | 89 | * **IPC (Electron's `ipcMain` and `ipcRenderer`):** The primary mechanism for structured data exchange between processes. Preload scripts (`preload.js`, `preload-aux.js`) establish secure channels for this communication. This is likely a *major* component of any "MCP". 90 | * **Webview `postMessage`:** Webviews use `postMessage` to send data to the extension host (via the renderer process) and receive data using `onmessage` event listeners. This is used for custom UI elements and is *another key candidate* for context passing. 91 | * **VS Code API (Extension Context):** Extensions receive a context object (`vscode.ExtensionContext`) during activation. This context provides access to: 92 | * `globalState`: A key-value store for persisting data across sessions (globally). 93 | * `workspaceState`: A key-value store for persisting data within the current workspace. 94 | * `subscriptions`: A mechanism for managing disposables (like event listeners) to prevent memory leaks. 95 | * `extensionUri`: The URI of the extension's directory. 96 | * `storageUri`: A URI for the extension's local storage. 97 | * `globalStorageUri`: A URI for the extension's global storage. 98 | * `environmentVariableCollection`: For managing environment variables. 99 | * `secrets`: For storing secrets. 100 | * **Command Contexts:** VS Code commands can receive context information when they are executed. This context can include information about the active editor, selected text, and other relevant data. This is often passed as arguments to command handlers. 101 | * **`data-vscode-context` Attribute (Webviews):** As seen in `index-no-csp.html` and `index.html`, HTML elements within webviews can have a `data-vscode-context` attribute. This attribute stores a JSON object containing contextual information. This is *highly likely* to be part of the "MCP," as it's a direct way to embed context within the UI. 102 | * **Drag and Drop Context:** The drag and drop events in `index.html` also show context being passed. 103 | 104 | ## 3. Deep Dive: `preload.js` and `preload-aux.js` 105 | 106 | These files are critical for understanding how context is *initially* passed to renderer processes. They establish the secure IPC channels. 107 | 108 | **`preload-aux.js` (Simplified and Annotated):** 109 | 110 | ```javascript 111 | // Requires Electron modules. This is safe in the preload script. 112 | const { ipcRenderer, webFrame, contextBridge } = require("electron"); 113 | 114 | // ... (Error handling and utility functions) ... 115 | 116 | // Expose a limited API to the renderer process via `window.vscode`. 117 | contextBridge.exposeInMainWorld("vscode", { 118 | // ... (Other exposed functions) ... 119 | 120 | // Wrapped IPC send. Enforces "vscode:" prefix for security. 121 | ipcRenderer: { 122 | send: (channel, ...args) => { 123 | if (!channel.startsWith("vscode:")) { 124 | console.error(`Invalid IPC channel: ${channel}`); 125 | return; 126 | } 127 | ipcRenderer.send(channel, ...args); 128 | }, 129 | invoke: async (channel, ...args) => { 130 | if (!channel.startsWith("vscode:")) { 131 | console.error(`Invalid IPC channel: ${channel}`); 132 | return; 133 | } 134 | return ipcRenderer.invoke(channel, ...args); 135 | }, 136 | }, 137 | 138 | // ... (Other exposed functions) ... 139 | }); 140 | ``` 141 | 142 | **`preload.js` (Conceptual Similarities):** 143 | 144 | The main `preload.js` follows a similar pattern, but for the primary renderer process. It also exposes a `vscode` object with wrapped IPC functions. 145 | 146 | **Key Takeaway:** The `vscode:` prefix enforced on IPC channels is a crucial security measure, but it also acts as a *namespace* for context-related messages. Any message sent through these channels could potentially carry contextual information. 147 | 148 | ## 4. Webview Context: `data-vscode-context` 149 | 150 | The `data-vscode-context` attribute is a direct way to embed context within webview UI elements. Let's revisit the relevant snippet from `index.html` (and `index-no-csp.html`): 151 | 152 | ```html 153 | 154 | 155 | 178 | ``` 179 | 180 | **Key Observations:** 181 | 182 | * **Context Accumulation:** The code searches up the DOM tree for `data-vscode-context` attributes, merging them into a single `context` object. This allows for hierarchical context, where more specific elements can override or extend the context of their parents. 183 | * **JSON Serialization:** The context is stored as a JSON string, which is a standard way to represent structured data. 184 | * **Message Passing:** The accumulated context is sent to the extension host via `hostMessaging.postMessage`. This is how the context from the UI becomes available to the extension's code. 185 | 186 | ## 5. Hypothesized "MCP" Flow (Focusing on Webviews) 187 | 188 | Based on the above analysis, here's a likely flow for how context is managed, particularly in scenarios involving webviews: 189 | 190 | ```mermaid 191 | sequenceDiagram 192 | participant Renderer as Renderer Process 193 | participant ExtensionHost as Extension Host Process 194 | participant Webview as Webview 195 | participant Main as Main Process 196 | 197 | Note over Renderer, ExtensionHost: Extension Activated (e.g., command invoked) 198 | ExtensionHost->>Renderer: Request Webview Creation 199 | Renderer->>Main: Create Webview (Window) 200 | Main->>Renderer: Webview Created 201 | Renderer->>Webview: Load HTML/JS (including preload script) 202 | 203 | Note over Webview: preload.js executes, exposing 'vscode' API 204 | 205 | Webview->>Webview: Render UI (potentially with data-vscode-context) 206 | 207 | Note over Webview, Renderer: User Interaction (e.g., right-click) 208 | 209 | Webview->>Webview: Gather Context (data-vscode-context) 210 | Webview->>Renderer: postMessage('did-context-menu', {context}) 211 | Renderer->>ExtensionHost: IPC Message (forwarded context) 212 | 213 | Note over ExtensionHost: Extension Code Processes Context 214 | ExtensionHost->>ExtensionHost: Process Context, Perform Actions 215 | 216 | ExtensionHost->>Renderer: IPC Response (optional) 217 | Renderer->>Webview: postMessage (response, optional) 218 | Webview->>Webview: Update UI (optional) 219 | ``` 220 | 221 | **Explanation:** 222 | 223 | 1. **Extension Activation:** An extension is activated (e.g., by a user command or an event). 224 | 2. **Webview Creation:** The extension requests the creation of a webview. 225 | 3. **Preload Script:** The webview's preload script (`preload.js` or `preload-aux.js`) executes, exposing a limited API (`window.vscode`) to the webview's JavaScript code. 226 | 4. **UI Rendering:** The webview renders its UI. Elements within the UI *may* have `data-vscode-context` attributes containing contextual information. 227 | 5. **User Interaction:** The user interacts with the webview (e.g., right-clicks on an element). 228 | 6. **Context Gathering:** The webview's JavaScript code gathers the relevant context, potentially by traversing the DOM and collecting `data-vscode-context` attributes. 229 | 7. **Message Passing:** The webview sends a message (using `postMessage`) to the renderer process, including the gathered context. 230 | 8. **IPC Forwarding:** The renderer process forwards the message (and the context) to the extension host via IPC. 231 | 9. **Context Processing:** The extension host's code processes the context and performs the appropriate actions. 232 | 10. **Response (Optional):** The extension host may send a response back to the webview (via IPC and `postMessage`), which can then update the UI. 233 | 234 | ## 6. Locating "MCP" Handling: Where to Look 235 | 236 | While we haven't found a file explicitly named "MCP," the above analysis points to several key areas where the *logic* of context management and passing resides: 237 | 238 | * **Preload Scripts (`preload.js`, `preload-aux.js`):** These define the secure IPC channels and are the *first point of contact* for context passing to renderer processes. 239 | * **Webview HTML/JS Files (e.g., `index.html`, `index-no-csp.html`, `audioPreview.js`, `imagePreview.js`):** These files handle user interactions within webviews and gather context using `data-vscode-context` and other mechanisms. 240 | * **Extension Code (within `extensions/*`):** Extensions receive context through the VS Code API (e.g., `ExtensionContext`, command arguments) and process messages from webviews. The `cursor-*` extensions are particularly relevant for AI-related context. 241 | * **IPC Handlers (in Main, Renderer, and Extension Host processes):** Any code that handles IPC messages (using `ipcMain.on`, `ipcRenderer.on`, `ipcRenderer.send`, `ipcRenderer.invoke`) is potentially involved in context passing. 242 | * **VS Code API usage:** Any usage of the VS Code API related to state management (globalState, workspaceState) is relevant. 243 | 244 | To find the most relevant code, you should: 245 | 246 | 1. **Search for `data-vscode-context`:** This is a strong indicator of context being embedded in the UI. 247 | 2. **Search for `postMessage` and `onmessage`:** These are used for webview communication. 248 | 3. **Search for `ipcRenderer.send`, `ipcRenderer.invoke`, `ipcMain.on`, `ipcRenderer.on`:** These are used for IPC. 249 | 4. **Examine the `cursor-*` extensions:** These are likely to be heavily involved in AI-related context management. 250 | 5. **Look for uses of `globalState` and `workspaceState`:** These are used for persisting context. 251 | 6. **Examine command definitions and handlers:** Commands often receive context as arguments. 252 | 253 | By focusing on these areas and tracing the flow of data, you can gain a comprehensive understanding of how Cursor manages and passes context, effectively uncovering the implementation of its "Model Context Protocol," even if it's not explicitly named as such. 254 | 255 | ## 7. `ms-vscode.js-debug` Extension Analysis 256 | 257 | (Analysis of `package.json` and `src/extension.js`) 258 | 259 | **Debugger Context Flow:** 260 | 261 | ```mermaid 262 | sequenceDiagram 263 | participant User 264 | participant VSCode as VS Code 265 | participant Extension as ms-vscode.js-debug 266 | participant DebugAdapter as Debug Adapter (DAP) 267 | 268 | User->>VSCode: Start Debugging 269 | VSCode->>Extension: activate(context) 270 | VSCode->>Extension: resolveDebugConfiguration(folder, config) 271 | Extension->>VSCode: Resolved config 272 | VSCode->>Extension: startDebugging(folder, config) 273 | Extension->>DebugAdapter: Launch/Attach (DAP) 274 | DebugAdapter->>Extension: DAP Events 275 | Extension->>VSCode: Update UI 276 | loop Debugging 277 | User->>VSCode: Debug Actions 278 | VSCode->>Extension: Command 279 | Extension->>DebugAdapter: DAP Request 280 | DebugAdapter->>Extension: DAP Response 281 | Extension->>VSCode: Update UI 282 | end 283 | User->>VSCode: Stop Debugging 284 | VSCode->>Extension: stopDebugging() 285 | Extension->>DebugAdapter: Disconnect (DAP) 286 | Extension->>VSCode: Update UI 287 | ``` 288 | 289 | ## 8. Core Configuration Service Analysis 290 | 291 | (Analysis of core configuration files and how they use IPC) 292 | 293 | **Configuration Loading and Updating Flow (Hypothesized):** 294 | 295 | ```mermaid 296 | sequenceDiagram 297 | participant Renderer as Renderer Process 298 | participant Main as Main Process 299 | participant Extension as Extension 300 | participant ConfigService as ConfigurationService (Renderer) 301 | participant FileSystem as File System 302 | 303 | Note over Main: VS Code Starts Up 304 | Main->>FileSystem: Load User Settings (JSON) 305 | Main->>FileSystem: Load Workspace Settings (JSON) 306 | Main->>Main: Create Configuration Model 307 | Note over Renderer: Renderer Process Starts 308 | Renderer->>ConfigService: Create ConfigurationService 309 | ConfigService->>Main: Request Initial Configuration (IPC) 310 | Main->>ConfigService: Initial Configuration (IPC) 311 | Extension->>ConfigService: getConfiguration('myExtension') 312 | ConfigService->>ConfigService: Check Cache 313 | alt Cache Hit 314 | ConfigService->>Extension: Cached Value 315 | else Cache Miss 316 | ConfigService->>Main: Request Configuration Value (IPC) 317 | Main->>ConfigService: Configuration Value (IPC) 318 | ConfigService->>ConfigService: Update Cache 319 | ConfigService->>Extension: Configuration Value 320 | end 321 | Note over Main, Renderer: User Changes a Setting 322 | Renderer->>ConfigService: updateValue('myExtension.setting', newValue) 323 | ConfigService->>Main: Update Configuration Value (IPC) 324 | Main->>Main: Update Configuration Model 325 | Main->>FileSystem: Save Settings to Disk (JSON) 326 | Main->>Renderer: Configuration Changed Event (IPC) 327 | ConfigService->>ConfigService: Update Cache 328 | ConfigService->>Extension: onDidChangeConfiguration Event 329 | Extension->>Extension: React to Configuration Change 330 | ``` 331 | 332 | ## 9. Product Configuration Analysis 333 | 334 | Analysis of `product.json` reveals important configuration details about how Cursor manages its servers and extensions: 335 | 336 | **Server Configuration:** 337 | * **Server Components:** 338 | * `serverApplicationName`: "cursor-server" 339 | * `serverDataFolderName`: ".cursor-server" 340 | * `tunnelApplicationName`: "cursor-tunnel" 341 | * `serverDownloadUrlTemplate`: "https://cursor.blob.core.windows.net/remote-releases/${commit}/vscode-reh-${os}-${arch}.tar.gz" 342 | 343 | * **Marketplace Configuration:** 344 | * `extensionsGallery.serviceUrl`: "https://marketplace.cursorapi.com/_apis/public/gallery" 345 | * `extensionsGallery.itemUrl`: "https://marketplace.cursorapi.com/items" 346 | 347 | * **Application Paths:** 348 | * `dataFolderName`: ".cursor" (This is where user-specific data and configurations are likely stored) 349 | * `applicationName`: "cursor" 350 | 351 | * **Extension Management:** 352 | * Skips packaging of certain local extensions: 353 | * "cursor-experiments" 354 | * "cursor-context-ast-typescript" 355 | * "cursor-browser" 356 | * "cursor-pyright" 357 | * These extensions might contain development or experimental features 358 | 359 | **Implications for MCP Configuration:** 360 | 361 | 1. **Data Location:** The `.cursor` folder (specified by `dataFolderName`) is likely where MCP-related configurations are stored locally. 362 | 363 | 2. **Server Architecture:** 364 | * The presence of both `cursor-server` and `cursor-tunnel` suggests a sophisticated server architecture 365 | * This might explain the "supa3" and "context" servers - they could be different instances or roles of the `cursor-server` 366 | 367 | 3. **Extension Handling:** 368 | * The `cursor-context-ast-typescript` extension being in `skipPackagingLocalExtensions` suggests it might be part of the MCP system 369 | * This extension likely handles TypeScript/JavaScript context analysis 370 | 371 | **Next Steps:** 372 | 373 | 1. **Examine Local Data:** 374 | * Look in the `.cursor` directory for configuration files 375 | * Check the `.cursor-server` directory for server-specific settings 376 | 377 | 2. **Investigate Extensions:** 378 | * Analyze the `cursor-context-ast-typescript` extension 379 | * Look for connections between the skipped extensions and MCP functionality 380 | 381 | 3. **Server Investigation:** 382 | * Examine how `cursor-server` and `cursor-tunnel` are configured 383 | * Look for configuration files that might specify "supa3" and "context" server details -------------------------------------------------------------------------------- /hack_claude.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Claude 3.7 Hack Script with automated backups 4 | 5 | This script enhances Claude 3.7 in Cursor by: 6 | 1. Increasing token limit to 200,000 7 | 2. Setting thinking level to "high" 8 | 3. Customizing Claude 3.7 UI styling 9 | 10 | The script uses precise string matching to find the target functions: 11 | - Token limit: Uses multiple search patterns for 'getEffectiveTokenLimit' with fallback to regex 12 | - Thinking level: Searches for 'getModeThinkingLevel(e)' 13 | - UI styling: Searches for '_serializableTitle:()=>"claude-3.7-sonnet"}' 14 | """ 15 | 16 | import os 17 | import re 18 | import sys 19 | import shutil 20 | import argparse 21 | from datetime import datetime 22 | 23 | def create_backup(file_path): 24 | """Create a backup of the target file.""" 25 | backup_file = f"{file_path}.backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}" 26 | shutil.copy2(file_path, backup_file) 27 | print(f"Backup created at: {backup_file}") 28 | return backup_file 29 | 30 | def modify_token_limit(content, mode="claude37_only"): 31 | """ 32 | Modify the getEffectiveTokenLimit function to increase the token limit. 33 | 34 | Args: 35 | content: The file content 36 | mode: "claude37_only" or "all_models" 37 | 38 | Returns: 39 | Modified content 40 | """ 41 | # Try multiple search patterns to find the function 42 | patterns = [ 43 | 'async getEffectiveTokenLimit(e)', # Original exact match 44 | 'async getEffectiveTokenLimit', # More relaxed function name match 45 | 'getEffectiveTokenLimit', # Even more relaxed match 46 | 'function getEffectiveTokenLimit' # Alternative declaration style 47 | ] 48 | 49 | match_pos = -1 50 | for pattern in patterns: 51 | match_pos = content.find(pattern) 52 | if match_pos != -1: 53 | print(f"Found token limit function using pattern: {pattern}") 54 | break 55 | 56 | if match_pos == -1: 57 | # Try regex as a fallback for maximum flexibility 58 | import re 59 | rx_pattern = r'(?:async\s+)?(?:function\s+)?getEffectiveTokenLimit\s*\(\s*\w+\s*\)' 60 | match = re.search(rx_pattern, content) 61 | if match: 62 | match_pos = match.start() 63 | print(f"Found token limit function using regex fallback") 64 | else: 65 | print("WARNING: Could not find getEffectiveTokenLimit function.") 66 | return content 67 | 68 | # Find the opening brace after the pattern 69 | opening_brace_pos = content.find('{', match_pos) 70 | if opening_brace_pos == -1: 71 | print("WARNING: Could not find opening brace for getEffectiveTokenLimit function.") 72 | return content 73 | 74 | # Find the matching closing brace (considering nested braces) 75 | brace_count = 1 76 | pos = opening_brace_pos + 1 77 | while brace_count > 0 and pos < len(content): 78 | if content[pos] == '{': 79 | brace_count += 1 80 | elif content[pos] == '}': 81 | brace_count -= 1 82 | pos += 1 83 | 84 | if brace_count != 0: 85 | print("WARNING: Could not find matching closing brace for getEffectiveTokenLimit function.") 86 | return content 87 | 88 | # Extract the original function 89 | original_function = content[match_pos:pos] 90 | 91 | # Create the replacement based on mode 92 | if mode == "claude37_only": 93 | # Only apply to Claude 3.7 models 94 | replacement = '''async getEffectiveTokenLimit(e) { 95 | if(e.modelName && e.modelName.includes('claude-3.7')) return 200000; 96 | 97 | // Original function code below 98 | ''' + original_function[original_function.find('{')+1:] 99 | else: 100 | # Apply to all models 101 | replacement = '''async getEffectiveTokenLimit(e) { 102 | return 200000; // Always use 200K limit for all models 103 | 104 | // Original function code will never run 105 | ''' + original_function[original_function.find('{')+1:] 106 | 107 | # Replace the function in the content 108 | modified_content = content[:match_pos] + replacement + content[pos:] 109 | 110 | if modified_content == content: 111 | print("WARNING: Failed to modify token limit function.") 112 | else: 113 | print("Token limit function modified successfully.") 114 | 115 | return modified_content 116 | 117 | def modify_thinking_level(content): 118 | """Modify the getModeThinkingLevel function to always return 'high'.""" 119 | # Find the function using the exact pattern requested 120 | pattern = 'getModeThinkingLevel(e)' 121 | 122 | # Find the function in the content 123 | match_pos = content.find(pattern) 124 | if match_pos == -1: 125 | print("WARNING: Could not find getModeThinkingLevel function.") 126 | return content 127 | 128 | # Find the opening brace after the pattern 129 | opening_brace_pos = content.find('{', match_pos) 130 | if opening_brace_pos == -1: 131 | print("WARNING: Could not find opening brace for getModeThinkingLevel function.") 132 | return content 133 | 134 | # Find the matching closing brace (considering nested braces) 135 | brace_count = 1 136 | pos = opening_brace_pos + 1 137 | while brace_count > 0 and pos < len(content): 138 | if content[pos] == '{': 139 | brace_count += 1 140 | elif content[pos] == '}': 141 | brace_count -= 1 142 | pos += 1 143 | 144 | if brace_count != 0: 145 | print("WARNING: Could not find matching closing brace for getModeThinkingLevel function.") 146 | return content 147 | 148 | # Extract the original function 149 | original_function = content[match_pos:pos] 150 | 151 | # Simple replacement 152 | replacement = '''getModeThinkingLevel(e) { 153 | return "high"; 154 | }''' 155 | 156 | # Replace the function in the content 157 | modified_content = content[:match_pos] + replacement + content[pos:] 158 | 159 | if modified_content == content: 160 | print("WARNING: Failed to modify thinking level function.") 161 | else: 162 | print("Thinking level function modified successfully.") 163 | 164 | return modified_content 165 | 166 | def modify_ui_styling(content, style="gradient"): 167 | """ 168 | Modify the Claude 3.7 UI styling. 169 | 170 | Args: 171 | content: The file content 172 | style: "gradient", "red", or "animated" 173 | 174 | Returns: 175 | Modified content 176 | """ 177 | # Use the exact search pattern as requested 178 | search_pattern = '_serializableTitle:()=>"claude-3.7-sonnet"}' 179 | 180 | # Find the pattern in the content 181 | match_pos = content.find(search_pattern) 182 | if match_pos == -1: 183 | print("WARNING: Could not find UI styling pattern.") 184 | return content 185 | 186 | # Find the start of the object (looking for 'a=' or 'a =' before the pattern) 187 | line_start = content.rfind('a=', 0, match_pos) 188 | if line_start == -1: 189 | line_start = content.rfind('a =', 0, match_pos) 190 | if line_start == -1: 191 | print("WARNING: Could not find the start of the UI styling object.") 192 | return content 193 | 194 | # Find the end of the object (the closing brace is already in our search pattern) 195 | line_end = match_pos + len(search_pattern) 196 | 197 | # Extract the original line 198 | original_line = content[line_start:line_end] 199 | 200 | # Define the replacements based on style 201 | if style == "gradient": 202 | replacement = 'a={...e,title:"claude-3.7-sonnet",id:r,subTitle:"HACKED",subTitleClass:"!opacity-100 gradient-text-high font-bold",_serializableTitle:()=>"3.7 Hacked"}' 203 | elif style == "red": 204 | replacement = 'a={...e,title:"claude-3.7-sonnet",id:r,subTitle:"HACKED",subTitleClass:"!opacity-100 text-red-600 font-bold",_serializableTitle:()=>"3.7 Hacked"}' 205 | elif style == "animated": 206 | replacement = 'a={...e,title:"claude-3.7-sonnet",id:r,subTitle:"HACKED",subTitleClass:"!opacity-100 text-red-500 animate-pulse font-bold",_serializableTitle:()=>"3.7 Hacked"}' 207 | 208 | # Replace the original line in the content 209 | modified_content = content[:line_start] + replacement + content[line_end:] 210 | 211 | if modified_content == content: 212 | print("WARNING: Failed to modify UI styling.") 213 | else: 214 | print("UI styling modified successfully.") 215 | 216 | return modified_content 217 | 218 | def modify_file(file_path, token_mode="claude37_only", ui_style="gradient", skip_backup=False): 219 | """Apply all modifications to the specified file.""" 220 | try: 221 | # Check if file exists 222 | if not os.path.isfile(file_path): 223 | print(f"Error: File not found: {file_path}") 224 | return False 225 | 226 | # Create backup unless skipped 227 | if not skip_backup: 228 | create_backup(file_path) 229 | 230 | # Read file content 231 | with open(file_path, 'r', encoding='utf-8') as f: 232 | content = f.read() 233 | 234 | # Apply modifications 235 | print("Applying modifications...") 236 | content = modify_token_limit(content, token_mode) 237 | content = modify_thinking_level(content) 238 | content = modify_ui_styling(content, ui_style) 239 | 240 | # Write modified content back to file 241 | with open(file_path, 'w', encoding='utf-8') as f: 242 | f.write(content) 243 | 244 | print(f"Successfully modified: {file_path}") 245 | return True 246 | 247 | except Exception as e: 248 | print(f"Error modifying file: {e}") 249 | return False 250 | 251 | def find_cursor_workbench_file(): 252 | """Try to find the Cursor workbench.desktop.main.js file in common locations.""" 253 | potential_paths = [ 254 | # macOS paths 255 | "/Applications/Cursor.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js", 256 | os.path.expanduser("~/Applications/Cursor.app/Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js"), 257 | 258 | # Windows paths 259 | "C:\\Program Files\\Cursor\\resources\\app\\out\\vs\\workbench\\workbench.desktop.main.js", 260 | "C:\\Program Files (x86)\\Cursor\\resources\\app\\out\\vs\\workbench\\workbench.desktop.main.js", 261 | os.path.expanduser("~\\AppData\\Local\\Programs\\Cursor\\resources\\app\\out\\vs\\workbench\\workbench.desktop.main.js"), 262 | 263 | # Linux paths 264 | "/usr/share/cursor/resources/app/out/vs/workbench/workbench.desktop.main.js", 265 | os.path.expanduser("~/.local/share/cursor/resources/app/out/vs/workbench/workbench.desktop.main.js") 266 | ] 267 | 268 | for path in potential_paths: 269 | if os.path.isfile(path): 270 | return path 271 | 272 | return None 273 | 274 | def main(): 275 | """Main function to parse arguments and run the script.""" 276 | parser = argparse.ArgumentParser(description="Hack Claude 3.7 in Cursor") 277 | 278 | parser.add_argument("--file", "-f", help="Path to workbench.desktop.main.js file") 279 | parser.add_argument("--token-mode", "-t", choices=["claude37_only", "all_models"], 280 | default="claude37_only", help="Token limit mode") 281 | parser.add_argument("--ui-style", "-u", choices=["gradient", "red", "animated"], 282 | default="gradient", help="UI styling mode") 283 | parser.add_argument("--skip-backup", "-s", action="store_true", 284 | help="Skip creating a backup file") 285 | 286 | args = parser.parse_args() 287 | 288 | # If file path not provided, try to find it 289 | if not args.file: 290 | detected_file = find_cursor_workbench_file() 291 | if detected_file: 292 | print(f"Found Cursor workbench file at: {detected_file}") 293 | args.file = detected_file 294 | else: 295 | print("Could not automatically detect Cursor workbench.desktop.main.js file.") 296 | print("Please provide the file path using the --file option.") 297 | return 1 298 | 299 | # Perform the modifications 300 | success = modify_file(args.file, args.token_mode, args.ui_style, args.skip_backup) 301 | 302 | if success: 303 | print("\nHack complete! You may need to restart Cursor for changes to take effect.") 304 | print("\nModifications applied:") 305 | if args.token_mode == "claude37_only": 306 | print("- Token limit set to 200,000 for Claude 3.7 models only") 307 | else: 308 | print("- Token limit set to 200,000 for ALL models") 309 | print("- Thinking level set to HIGH for all conversations") 310 | print(f"- UI styling set to {args.ui_style.upper()} mode") 311 | return 0 312 | else: 313 | print("\nHack failed. Please check the error messages above.") 314 | return 1 315 | 316 | if __name__ == "__main__": 317 | sys.exit(main()) 318 | --------------------------------------------------------------------------------