Meta的Pyrefly在不知情的情况下破坏竞争的Python扩展。
Meta's Pyrefly sabotages competing Python extensions without telling you

原始链接: https://github.com/facebook/pyrefly/issues/3292

## Pyrefly 扩展行为总结 Pyrefly VS Code 扩展在激活时,会静默禁用其他竞争的 Python 语言服务器扩展(特别是 `detachhead.basedpyright`、`codeium.windsurfpyright` 和 `anysphere.cursorpyright`),方法是修改用户的全局 VS Code 设置。它通过在每个目标扩展的设置中将 `disableLanguageServices = true`,在不通知用户的情况下实现这一点。 重要的是,此更改是**永久的**;即使在停用或卸载 Pyrefly 时,也不会恢复这些设置,导致禁用的扩展损坏,直到用户手动修复。当打开 Python 文件时,此行为会无条件触发。 此外,Pyrefly 强制依赖微软的 Python 扩展 (`ms-python.python`、`ms-python.debugpy`、`ms-python.vscode-python-envs`),即使对于有意避免使用微软产品(例如使用 VSCodium 的用户)也会强制安装它们。 这种依赖似乎是不必要的,因为 Pyrefly 的核心功能并不依赖于它们。 由于扩展的静默全局修改和缺乏清理,其行为被认为是有问题的,从而造成了糟糕的用户体验和潜在的困惑。

## Meta 的 Pyrefly 在未经同意的情况下更改用户设置 Meta 的新型 Python 类型检查器 Pyrefly 被发现会在安装时,通过修改用户的全局设置,静默禁用竞争的 VS Code 扩展(basedpyright、windsurfpyright 和 cursorpyright)。这种更改以纯 TypeScript 编写,即使在卸载 Pyrefly 后仍然存在,导致被禁用的扩展无法正常工作。 Meta 的一名开发者承认这是一个 beta 版本发布时疏忽大意的问题,并在 GitHub 上发布了修复方案——在更改设置前提示用户,并在停用时恢复设置。 这一发现引发了争论,一些人称之为恶意行为,而另一些人则认为这是为了避免语言服务器之间的冲突,从而改善用户体验的一种务实但执行不佳的尝试。 许多评论员指出,Python 环境很容易受到软件包安装的破坏,以及普遍对 Meta 产品中意外行为的不信任。
相关文章

原文

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

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 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 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 reproduction

Reproduced independently on both VSCodium and stock VS Code 1.118.1.

Test 1 — VSCodium

Tested 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 behavior

If Pyrefly needs exclusive access to Python language services to function correctly,
it should:

  1. Ask the user before modifying settings owned by other extensions
  2. Restore those settings in deactivate() when Pyrefly is disabled or uninstalled
  3. Or at minimum, log what it changed so users can reverse it

Additional concern: forced Microsoft extension dependencies

package.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

  1. Install detachhead.basedpyright and confirm it is working (completions, hover, etc.)
  2. Install meta.pyrefly
  3. Open a Python file (triggers Pyrefly activation)
  4. Check your global settings.jsonbasedpyright.disableLanguageServices is now true
  5. Uninstall meta.pyrefly
  6. Observe that basedpyright.disableLanguageServices remains true — basedpyright
    is still broken with no indication of why
联系我们 contact @ memedata.com