Start working on refreshing Python docs (#37880)

Cole Miller , Katie Geer , and Piotr created

- Reflect that basedpyright is the new primary language server
- Discuss Ruff
- Deemphasize manual venv configuration for language servers

Release Notes:

- N/A

---------

Co-authored-by: Katie Geer <katie@zed.dev>
Co-authored-by: Piotr <piotr@zed.dev>

Change summary

docs/src/SUMMARY.md               |   1 
docs/src/configuring-languages.md |   6 
docs/src/languages/python.md      | 285 +++++++++++++++++++++++++-------
docs/src/toolchains.md            |  28 +++
4 files changed, 258 insertions(+), 62 deletions(-)

Detailed changes

docs/src/SUMMARY.md 🔗

@@ -15,6 +15,7 @@
 
 - [Configuring Zed](./configuring-zed.md)
 - [Configuring Languages](./configuring-languages.md)
+  - [Toolchains](./toolchains.md)
 - [Key bindings](./key-bindings.md)
   - [All Actions](./all-actions.md)
 - [Snippets](./snippets.md)

docs/src/configuring-languages.md 🔗

@@ -135,6 +135,12 @@ In this example:
 
 This configuration allows you to tailor the language server setup to your specific needs, ensuring that you get the most suitable functionality for your development workflow.
 
+### Toolchains
+
+Some language servers need to be configured with a current "toolchain", which is an installation of a specific version of a programming language compiler or/and interpreter, which can possibly include a full set of dependencies of a project.
+An example of what Zed considers a toolchain is a virtual environment in Python.
+Not all languages in Zed support toolchain discovery and selection, but for those that do, you can specify the toolchain from a toolchain picker (via {#action toolchain::Select}). To learn more about toolchains in Zed, see [`toolchains`](./toolchains.md).
+
 ### Configuring Language Servers
 
 Many language servers accept custom configuration options. You can set these in the `lsp` section of your `settings.json`:

docs/src/languages/python.md 🔗

@@ -1,59 +1,134 @@
-# Python
+# How to Set Up Python in Zed
 
 Python support is available natively in Zed.
 
 - Tree-sitter: [tree-sitter-python](https://github.com/zed-industries/tree-sitter-python)
 - Language Servers:
+  - [DetachHead/basedpyright](https://github.com/DetachHead/basedpyright)
+  - [astral-sh/ruff](https://github.com/astral-sh/ruff)
+  - [astral-sh/ty](https://github.com/astral-sh/ty)
   - [microsoft/pyright](https://github.com/microsoft/pyright)
   - [python-lsp/python-lsp-server](https://github.com/python-lsp/python-lsp-server) (PyLSP)
 - Debug Adapter: [debugpy](https://github.com/microsoft/debugpy)
 
-## Language Servers
+## Install Python
 
-Zed supports multiple Python language servers some of which may require configuration to work properly.
+You'll need both Zed and Python installed before you can begin.
 
-See: [Working with Language Servers](https://zed.dev/docs/configuring-languages#working-with-language-servers) for more information.
+### Step 1: Install Python
 
-## Virtual Environments in the Terminal {#terminal-detect_venv}
+Zed does not bundle a Python runtime, so you’ll need to install one yourself.
+Choose one of the following options:
 
-Zed will detect Python virtual environments and automatically activate them in terminal if available.
-See: [detect_venv documentation](../configuring-zed.md#terminal-detect_venv) for more.
+- uv (recommended)
 
-## PyLSP
+```bash
+curl -LsSf https://astral.sh/uv/install.sh | sh
+```
 
-[python-lsp-server](https://github.com/python-lsp/python-lsp-server/), more commonly known as PyLSP, by default integrates with a number of external tools (autopep8, mccabe, pycodestyle, yapf) while others are optional and must be explicitly enabled and configured (flake8, pylint).
+To learn more, visit [Astral’s installation guide](https://docs.astral.sh/uv/getting-started/installation/).
 
-See [Python Language Server Configuration](https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md) for more.
+- Homebrew:
+
+```bash
+brew install python
+```
+
+- Python.org installer: Download the latest version from [python.org/downloads](https://python.org/downloads).
+
+### Step 2: Verify Python Installation
+
+Confirm Python is installed and available in your shell:
+
+```bash
+python3 --version
+```
+
+You should see an output like `Python 3.x.x`.
+
+## Open Your First Python Project in Zed
+
+Once Zed and Python are installed, open a folder containing Python code to start working.
+
+### Step 1: Launch Zed with a Python Project
+
+Open Zed.
+From the menu bar, choose File > Open Folder, or launch from the terminal:
+
+```bash
+zed path/to/your/project
+```
+
+Zed will recognize `.py` files automatically using its native tree-sitter-python parser, with no plugins or manual setup required.
+
+### Step 2: Use the Integrated Terminal (Optional)
+
+Zed includes an integrated terminal, accessible from the bottom panel. If Zed detects that your project is using a [virtual environment](#virtual-environments), it will be activated automatically in newly-created terminals. You can configure this behavior with the [`detect_venv`](../configuring-zed.md#terminal-detect_venv) setting.
+
+## Configure Python Language Servers in Zed
+
+Zed provides several Python language servers out of the box. By default, [basedpyright](https://github.com/DetachHead/basedpyright) is the primary language server, and [Ruff](https://github.com/astral-sh/ruff) is used for formatting and linting.
 
-## PyRight
+Other built-in language servers are:
 
-### PyRight Configuration
+- [Ty](https://docs.astral.sh/ty/)&mdash;Up-and-coming language server from Astral, built for speed.
+- [Pyright](https://github.com/microsoft/pyright)&mdash;The basis for basedpyright.
+- [PyLSP](https://github.com/python-lsp/python-lsp-server)&mdash;A plugin-based language server that integrates with tools like `pycodestyle`, `autopep8`, and `yapf`.
 
-The [pyright](https://github.com/microsoft/pyright) language server offers flexible configuration options specified in a JSON-formatted text configuration. By default, the file is called `pyrightconfig.json` and is located within the root directory of your project. Pyright settings can also be specified in a `[tool.pyright]` section of a `pyproject.toml` file. A `pyrightconfig.json` file always takes precedence over `pyproject.toml` if both are present.
+These are disabled by default, but can be enabled in your settings. For example:
 
-For more information, see the Pyright [configuration documentation](https://microsoft.github.io/pyright/#/configuration).
+```json
+{
+  "languages": {
+    "Python": {
+      "language_servers": {
+        // Disable basedpyright and enable Ty, and otherwise
+        // use the default configuration.
+        "ty", "!basedpyright", ".."
+      }
+    }
+  }
+}
+```
+
+See: [Working with Language Servers](https://zed.dev/docs/configuring-languages#working-with-language-servers) for more information about how to enable and disable language servers.
+
+### Basedpyright
+
+[basedpyright](https://docs.basedpyright.com/latest/) is the primary Python language server in Zed beginning with Zed v0.204.0. It provides core language server functionality like navigation (go to definition/find all references) and type checking. Compared to Pyright, it adds support for additional language server features (like inlay hints) and checking rules.
+
+Note that while basedpyright in isolation defaults to the `recommended` [type-checking mode](https://docs.basedpyright.com/latest/benefits-over-pyright/better-defaults/#typecheckingmode), Zed configures it to use the less-strict `standard` mode by default, which matches the behavior of Pyright. You can set the type-checking mode for your project using the `typeCheckingMode` setting in `pyrightconfig.json` or `pyproject.toml`, which will override Zed's default. Read on more for more details about how to configure basedpyright.
 
-### PyRight Settings
+#### Basedpyright Configuration
 
-The [pyright](https://github.com/microsoft/pyright) language server also accepts specific LSP-related settings, not necessarily connected to a project. These can be changed in the `lsp` section of your `settings.json`.
+basedpyright reads configuration options from two different kinds of sources:
+
+- Language server settings ("workspace configuration"), which must be configured per-editor (using `settings.json` in Zed's case) but apply to all projects opened in that editor
+- Configuration files (`pyrightconfig.json`, `pyproject.toml`), which are editor-independent but specific to the project where they are placed
+
+As a rule of thumb, options that are only relevant when using basedpyright from an editor must be set in language server settings, and options that are relevant even if you're running it [as a command-line tool](https://docs.basedpyright.com/latest/configuration/command-line/) must be set in configuration files. Settings related to inlay hints are examples of the first category, and the [diagnostic category](https://docs.basedpyright.com/latest/configuration/config-files/#diagnostic-categories) settings are examples of the second category.
+
+Examples of both kinds of configuration are provided below. Refer to the basedpyright documentation on [language server settings](https://docs.basedpyright.com/latest/configuration/language-server-settings/) and [configuration files](https://docs.basedpyright.com/latest/configuration/config-files/) for comprehensive lists of available options.
+
+##### Language server settings
+
+Language server settings for basedpyright in Zed can be set in the `lsp` section of your `settings.json`.
 
 For example, in order to:
 
-- use strict type-checking level
 - diagnose all files in the workspace instead of the only open files default
-- provide the path to a specific Python interpreter
+- disable inlay hints on function arguments
+
+You can use the following configuration:
 
 ```json
 {
   "lsp": {
-    "pyright": {
+    "basedpyright": {
       "settings": {
-        "python.analysis": {
+        "basedpyright.analysis": {
           "diagnosticMode": "workspace",
-          "typeCheckingMode": "strict"
-        },
-        "python": {
-          "pythonPath": ".venv/bin/python"
+          "inlayHints.callArgumentNames": false
         }
       }
     }
@@ -61,54 +136,103 @@ For example, in order to:
 }
 ```
 
-For more information, see the Pyright [settings documentation](https://microsoft.github.io/pyright/#/settings).
+##### Configuration files
+
+basedpyright reads project-specific configuration from the `pyrightconfig.json` configuration file and from the `[tool.basedpyright]` and `[tool.pyright]` sections of `pyproject.toml` manifests. `pyrightconfig.json` overrides `pyproject.toml` if configuration is present in both places.
+
+Here's an example `pyrightconfig.json` file that configures basedpyright to use the `strict` type-checking mode and not to issue diagnostics for any files in `__pycache__` directories:
+
+```json
+{
+  "typeCheckingMode": "strict",
+  "ignore": ["**/__pycache__"]
+}
+```
+
+### PyLSP
 
-### Pyright Virtual environments
+[python-lsp-server](https://github.com/python-lsp/python-lsp-server/), more commonly known as PyLSP, by default integrates with a number of external tools (autopep8, mccabe, pycodestyle, yapf) while others are optional and must be explicitly enabled and configured (flake8, pylint).
+
+See [Python Language Server Configuration](https://github.com/python-lsp/python-lsp-server/blob/develop/CONFIGURATION.md) for more.
 
-A Python [virtual environment](https://docs.python.org/3/tutorial/venv.html) allows you to store all of a project's dependencies, including the Python interpreter and package manager, in a single directory that's isolated from any other Python projects on your computer.
+## Virtual Environments
 
-By default, the Pyright language server will look for Python packages in the default global locations. But you can also configure Pyright to use the packages installed in a given virtual environment.
+[Virtual environments](https://docs.python.org/3/library/venv.html) are a useful tool for fixing a Python version and set of dependencies for a specific project, in a way that's isolated from other projects on the same machine. Zed has built-in support for discovering, configuring, and activating virtual environments, based on the language-agnostic concept of a [toolchain](../toolchains.md).
 
-To do this, create a JSON file called `pyrightconfig.json` at the root of your project. This file must include two keys:
+Note that if you have a global Python installation, it is also counted as a toolchain for Zed's purposes.
 
-- `venvPath`: a relative path from your project directory to any directory that _contains_ one or more virtual environment directories
-- `venv`: the name of a virtual environment directory
+### Create a Virtual Environment
 
-For example, a common approach is to create a virtual environment directory called `.venv` at the root of your project directory with the following commands:
+If your project doesn't have a virtual environment set up already, you can create one as follows:
 
-```sh
-# create a virtual environment in the .venv directory
+```bash
 python3 -m venv .venv
-# set up the current shell to use that virtual environment
-source .venv/bin/activate
 ```
 
-Having done that, you would create a `pyrightconfig.json` with the following content:
+Alternatively, if you're using `uv`, running `uv sync` will create a virtual environment the first time you run it.
+
+### How Zed Uses Python Toolchains
+
+Zed uses the selected Python toolchain for your project in the following ways:
+
+- Built-in language servers will be automatically configured with the path to the toolchain's Python interpreter and, if applicable, virtual environment. This is important so that they can resolve dependencies. (Note that language servers provided by extensions can't be automatically configured like this currently.)
+- Python tasks (such as pytest tests) will be run using the toolchain's Python interpreter.
+- If the toolchain is a virtual environment, the environment's activation script will be run automatically when you launch a new shell in Zed's integrated terminal, giving you convenient access to the selected Python interpreter and dependency set.
+- If a built-in language server is installed in the active virtual environment, that binary will be used instead of Zed's private automatically-installed binary. This also applies to debugpy.
+
+### Selecting a Toolchain
+
+For most projects, Zed will automatically select the right Python toolchain. In complex projects with multiple virtual environments, it might be necessary to override this selection. You can use the [toolchain selector](../toolchains.md#selecting-toolchains) to pick a toolchain from the list discovered by Zed, or [specify the path to a toolchain manually](../toolchains.md#adding-toolchains-manually) if it's not on the list.
+
+## Code Formatting & Linting
+
+Zed provides the [Ruff](https://docs.astral.sh/ruff/) formatter and linter for Python code. (Specifically, Zed runs Ruff as an LSP server using the `ruff server` subcommand.) Both formatting and linting are enabled by default, including format-on-save.
+
+### Configuring formatting
+
+You can disable format-on-save for Python files in your `settings.json`:
 
 ```json
 {
-  "venvPath": ".",
-  "venv": ".venv"
+  "languages": {
+    "Python": {
+      "format_on_save": false
+    }
+  }
 }
 ```
 
-If you prefer to use a `pyproject.toml` file, you can add the following section:
+Alternatively, you can use the `black` command-line tool for Python formatting, while keeping Ruff enabled for linting:
 
-```toml
-[tool.pyright]
-venvPath = "."
-venv = ".venv"
+```json
+{
+  "languages": {
+    "Python": {
+      "formatter": {
+        "external": {
+          "command": "black",
+          "arguments": ["--stdin-filename", "{buffer_path}", "-"]
+        }
+      }
+      // Or use `"formatter": null` to disable formatting entirely.
+    }
+  }
+}
 ```
 
-You can also configure this option directly in your `settings.json` file ([pyright settings](#pyright-settings)), as recommended in [Configuring Your Python Environment](https://microsoft.github.io/pyright/#/import-resolution?id=configuring-your-python-environment).
+### Configuring Ruff
+
+Like basedpyright, Ruff reads options from both Zed's language server settings and configuration files (`ruff.toml`) when used in Zed. Unlike basedpyright, _all_ options can be configured in either of these locations, so the choice of where to put your Ruff configuration comes down to whether you want it to be shared between projects but specific to Zed (in which case you should use language server settings), or specific to one project but common to all Ruff invocations (in which case you should use `ruff.toml`).
+
+Here's an example of using language server settings in Zed's `settings.json` to disable all Ruff lints in Zed (while still using Ruff as a formatter):
 
 ```json
 {
   "lsp": {
-    "pyright": {
-      "settings": {
-        "python": {
-          "pythonPath": ".venv/bin/python"
+    "ruff": {
+      "initialization_options": {
+        "settings": {
+          "exclude": ["*"]
         }
       }
     }
@@ -116,24 +240,40 @@ You can also configure this option directly in your `settings.json` file ([pyrig
 }
 ```
 
-### Code formatting & Linting
+And here's an example `ruff.toml` with linting and formatting options, adapted from the Ruff documentation:
 
-The Pyright language server does not provide code formatting or linting. If you want to detect lint errors and reformat your Python code upon saving, you'll need to set up.
+```toml
+[lint]
+# Avoid enforcing line-length violations (`E501`)
+ignore = ["E501"]
 
-A common tool for formatting Python code is [Ruff](https://docs.astral.sh/ruff/). It is another tool written in Rust, an extremely fast Python linter and code formatter. It is available through the [Ruff extension](https://github.com/zed-industries/zed/tree/main/extensions/ruff/). To configure the Ruff extension to work within Zed, see the setup documentation [here](https://docs.astral.sh/ruff/editors/setup/#zed).
+[format]
+# Use single quotes when formatting.
+quote-style = "single"
+```
 
-<!--
-TBD: Expand Python Ruff docs.
-TBD: Ruff pyproject.toml, ruff.toml docs. `ruff.configuration`.
--->
+For more details, refer to the Ruff documentation about [configuration files](https://docs.astral.sh/ruff/configuration/) and [language server settings](https://docs.astral.sh/ruff/editors/settings/), and the [list of options](https://docs.astral.sh/ruff/settings/).
 
 ## Debugging
 
-Zed supports zero-configuration debugging of Python module entry points and pytest tests.
-Run {#action debugger::Start} ({#kb debugger::Start}) to see a contextual list for the current project.
-For greater control, you can add debug configurations to `.zed/debug.json`. See the examples below.
+Zed supports Python debugging through the `debugpy` adapter. You can start with no configuration or define custom launch profiles in `.zed/debug.json`.
+
+### Start Debugging with No Setup
+
+Zed can automatically detect debuggable Python entry points. Press F4 (or run debugger: start from the Command Palette) to see available options for your current project.
+This works for:
+
+- Python scripts
+- Modules
+- pytest tests
 
-### Debug Active File
+Zed uses `debugpy` under the hood, but no manual adapter configuration is required.
+
+### Define Custom Debug Configurations
+
+For reusable setups, create a `.zed/debug.json` file in your project root. This gives you more control over how Zed runs and debugs your code.
+
+#### Debug Active File
 
 ```json
 [
@@ -146,9 +286,11 @@ For greater control, you can add debug configurations to `.zed/debug.json`. See
 ]
 ```
 
-### Flask App
+This runs the file currently open in the editor.
 
-For a common Flask Application with a file structure similar to the following:
+#### Debug a Flask App
+
+For projects using Flask, you can define a full launch configuration:
 
 ```
 .venv/
@@ -190,3 +332,22 @@ requirements.txt
   }
 ]
 ```
+
+These can be combined to tailor the experience for web servers, test runners, or custom scripts.
+
+## Troubleshoot and Maintain a Productive Python Setup
+
+Zed is designed to minimize configuration overhead, but occasional issues can still arise—especially around environments, language servers, or tooling. Here's how to keep your Python setup working smoothly.
+
+### Resolve Language Server Startup Issues
+
+If a language server isn't responding or features like diagnostics or autocomplete aren't available:
+
+- Check your Zed log (using the {#action zed::OpenLog} action) for errors related to the language server you're trying to use. This is where you're likely to find useful information if the language server failed to start up at all.
+- Use the language server logs view to understand the lifecycle of the affected language server. You can access this view using the {#action dev::OpenLanguageServerLogs} action, or by clicking the lightning bolt icon in the status bar and selecting your language server. The most useful pieces of data in this view are:
+  - "Server Logs", which shows any errors printed by the language server
+  - "Server Info", which shows details about how the language server was started
+- Verify your `settings.json` or `pyrightconfig.json` is syntactically correct.
+- Restart Zed to reinitialize language server connections, or try restarting the language server using the {#action editor::RestartLanguageServer}
+
+If the language server is failing to resolve imports, and you're using a virtual environment, make sure that the right environment is chosen in the selector. You can use "Server Info" view to confirm which virtual environment Zed is sending to the language server&mdash;look for the `* Configuration` section at the end.

docs/src/toolchains.md 🔗

@@ -0,0 +1,28 @@
+# Toolchains
+
+Zed projects offer a dedicated UI for toolchain selection, which lets you pick a set of tools for working with a given language in a current project.
+Imagine you're working with Python project, which has virtual environments that encapsulate a set of dependencies of your project along with a suitable interpreter to run it with. The language server has to know which virtual environment you're working with, as it uses it to understand your project's code.
+With toolchain selector, you don't need to spend time configuring your language server to point it at the right virtual environment directory - you can just select the right virtual environment (toolchain) from a dropdown.
+You can even select different toolchains for different subprojects within your Zed project. A definition of a subproject is language-specific.
+In collaborative scenarios, only the project owner can see and modify an active toolchain.
+In [remote projects](./remote-development.md)., you can use the toolchain selector to control the active toolchain on the SSH host. When [sharing your project](./collaboration.md), the toolchain selector is not available to guests.
+
+## Why do we need toolchains?
+
+The active toolchain is relevant for launching language servers, which may need it to function properly - it may not be able to resolve dependencies, which in turn may make functionalities like "Go to definition" or "Code completions" unavailable.
+
+The active toolchain is also relevant when launching a shell in the terminal panel: some toolchains provide "activation scripts" for shells, which make those toolchains available in the shell environment for your convenience. Zed will run these activation scripts automatically when you create a new terminal.
+
+This also applies to [tasks](./tasks.md) - Zed tasks behave "as if" you opened a new terminal tab and ran a given task invocation yourself, which in turn means that Zed task execution is affected by the active toolchain and its activation script.
+
+## Selecting toolchains
+
+The active toolchain (if there is one) is displayed in the status bar (on the right hand side). Click on it to access the toolchain selector - you can also use an action from a command palette ({#action toolchain::Select}).
+
+Zed will automatically infer a set of toolchains to choose from based on the project you're working with. A default will also be selected on your behalf on a best-effort basis when you open a project for the first time.
+
+The toolchain selection applies to a current subproject, which - depending on the structure of your Zed project - might be your whole project or just a subset of it. For example, if you have a monorepo with multiple subprojects, you might want to select a different toolchain for each subproject.
+
+## Adding toolchains manually
+
+If automatic detection does not suffice for you, you can add toolchains manually. To do that, click on the "Add toolchain" button in the toolchain selector. From there you can provide a path to a toolchain and set a name of your liking for it.