Meta's Pyrefly sabotages competing Python extensions without telling you

Published: (May 2, 2026 at 12:34 PM EDT)
3 min read

Source: Hacker News

Affected extensions

  • detachhead.basedpyright
  • codeium.windsurfpyright
  • anysphere.cursorpyright

Source

lsp/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 functions are called unconditionally in lsp/src/extension.ts on activation.

Relevant commits: 69985d1d, c0ab0d76, 72458900, 2fb5205a (December 8‑9 2025).

Why this is a problem

  1. Silent global modification
    ConfigurationTarget.Global writes to the user’s global settings.json, affecting every workspace. No notification or prompt is shown.

  2. No cleanup on deactivation or uninstall
    There is no deactivate() logic that restores the modified settings. After uninstalling Pyrefly, the targeted extensions remain broken.

  3. Hard‑coded extension IDs
    The code disables specific competitor extensions by publisher ID rather than providing a generic conflict‑resolution mechanism. Users cannot opt out.

Live reproduction

Test 1 — VSCodium

  • Before installing Pyrefly (~/.config/VSCodium/User/settings.json):
{
  "python.languageServer": "Default"
}
  • After installing Pyrefly and opening a Python file:
{
  "python.languageServer": "Default",
  "basedpyright.disableLanguageServices": true
}
  • After uninstalling Pyrefly (key persists):
{
  "python.languageServer": "Default",
  "basedpyright.disableLanguageServices": true
}

Test 2 — VS Code 1.118.1 (clean isolated profile)

  • Before installing Pyrefly: settings.json does not exist (empty profile).

  • After installing detachhead.basedpyright, then meta.pyrefly, and opening a Python file:

{
  "python.languageServer": "None",
  "basedpyright.disableLanguageServices": true
}

The write occurs on the first Python file open, regardless of prior configuration.

Expected behavior

If Pyrefly requires exclusive access to Python language services, it should:

  • Prompt the user before modifying settings owned by other extensions.
  • Restore those settings in deactivate() when Pyrefly is disabled or uninstalled.
  • At minimum, log the changes so users can reverse them.

Additional concern: forced Microsoft extension dependencies

package.json declares "extensionDependencies": ["ms-python.python"]. This creates 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 functionality ms-python.python provides is querying the active Python interpreter for optional CodeLens buttons. Core LSP features (type checking, completions, hover, go‑to‑definition) run entirely through the pyrefly binary and have no dependency on ms-python.python. For users of VSCodium or other FOSS VS Code distributions who avoid Microsoft extensions, this hidden dependency is a significant side effect.

Steps to reproduce

  1. Install detachhead.basedpyright and verify it works (completions, hover, etc.).
  2. Install meta.pyrefly.
  3. Open a Python file (triggers Pyrefly activation).
  4. Check the global settings.json; basedpyright.disableLanguageServices will be true.
  5. Uninstall meta.pyrefly.
  6. Observe that basedpyright.disableLanguageServices remains true, leaving basedpyright broken with no indication why.
0 views
Back to Blog

Related posts

Read more »