Extension silently disables competitor extensions globally with no cleanup on uninstall
Pangram verdict · v3.3
We believe that this document is a mix of AI-generated, and human-written content
AI likelihood · overall
MixedArticle text · 599 words · 3 segments analyzed
On activation, Pyrefly silently writes disableLanguageServices = true to the user's global VS Code settings for three named third-party extensions, without prompting the user or notifying them in any way. These settings are never restored when Pyrefly is deactivated or uninstalled, leaving those extensions permanently broken until the user manually intervenes.This has been verified by live reproduction on a real machine (see below).Affected extensions detachhead.basedpyright codeium.windsurfpyright anysphere.cursorpyright Sourcelsp/src/extension-interop.ts:export async function disableWindsurfPyrightIfInstalled() { const windsurfPyrightExtension = vscode.extensions.getExtension('codeium.windsurfpyright'); if (windsurfPyrightExtension) { const config = vscode.workspace.getConfiguration('windsurfPyright'); await config.update('disableLanguageServices', true, vscode.ConfigurationTarget.Global); } }
export async function disableBasedPyrightIfInstalled() { const basedPyrightExtension = vscode.extensions.getExtension('detachhead.basedpyright'); if (basedPyrightExtension) { const config = vscode.workspace.getConfiguration('basedpyright'); await config.update('disableLanguageServices', true, vscode.ConfigurationTarget.Global); } }
export async function disableCursorPyrightIfInstalled() { const cursorPyrightExtension = vscode.extensions.getExtension('anysphere.cursorpyright'); if (cursorPyrightExtension) { const config = vscode.workspace.getConfiguration('cursorpyright'); await config.update('disableLanguageServices', true, vscode.ConfigurationTarget.Global); } }These are called unconditionally in lsp/src/extension.ts on activation.
Relevant commits: 69985d1d, c0ab0d76, 72458900, 2fb5205a (December 8-9, 2025)Why this is a problem1. Silent global modification ConfigurationTarget.Global writes to the user's global settings.json, affecting every workspace on the machine. The user receives no notification, no prompt, no indication this has occurred.2. No cleanup on deactivation or uninstall There is no corresponding deactivate() logic that restores these settings. A user who installs Pyrefly, then uninstalls it, is left with basedpyright, windsurfpyright, or cursorpyright silently broken — with no obvious cause. They would need to know to manually find and delete these keys from their global settings.json to restore functionality.3. Targets extensions by publisher ID This is not a generic "disable conflicting language servers" mechanism. It hardcodes the extension IDs of specific named competitors and disables them individually. The user has no opt-out.Live reproductionReproduced independently on both VSCodium and stock VS Code 1.118.1.Test 1 — VSCodiumTested with detachhead.basedpyright installed.~/.config/VSCodium/User/settings.json before installing Pyrefly:{ "python.languageServer": "Default" }After installing Pyrefly and opening a single Python file:{ "python.languageServer": "Default", "basedpyright.disableLanguageServices": true }After uninstalling Pyrefly:{ "python.languageServer": "Default", "basedpyright.disableLanguageServices": true }The key persists. basedpyright remains broken with no indication of why.Test 2 — VS Code 1.118.1 (clean isolated profile)To rule out any VSCodium-specific behaviour, reproduced on stock VS Code using a completely clean profile (--user-data-dir /tmp/vscode-test-profile) with no prior configuration.settings.json before installing Pyrefly: file did not exist (empty profile)After installing detachhead.basedpyright, then meta.pyrefly, and opening a single Python file:{ "python.languageServer": "None", "basedpyright.disableLanguageServices": true }Same result.
The write happens on first Python file open regardless of editor or prior configuration.Expected behaviorIf Pyrefly needs exclusive access to Python language services to function correctly, it should: Ask the user before modifying settings owned by other extensions Restore those settings in deactivate() when Pyrefly is disabled or uninstalled Or at minimum, log what it changed so users can reverse it Additional concern: forced Microsoft extension dependenciespackage.json declares "extensionDependencies": ["ms-python.python"].VSCodium and VS Code treat this as a hard bidirectional lock — installing Pyrefly automatically installs: ms-python.python ms-python.debugpy ms-python.vscode-python-envs Uninstalling any of those three also uninstalls Pyrefly.The only thing ms-python.python is used for is querying the active Python interpreter path for the optional "Run File / Run Test" CodeLens buttons. The core LSP features (type checking, completions, hover, go-to-definition) run entirely through the pyrefly binary and have no dependency on ms-python.python at all.For users on VSCodium or other FOSS VS Code distributions who specifically avoid Microsoft extensions, this is a significant and undisclosed side effect of installing what is presented as an independent open source tool.Steps to reproduce Install detachhead.basedpyright and confirm it is working (completions, hover, etc.) Install meta.pyrefly Open a Python file (triggers Pyrefly activation) Check your global settings.json — basedpyright.disableLanguageServices is now true Uninstall meta.pyrefly Observe that basedpyright.disableLanguageServices remains true — basedpyright is still broken with no indication of why