-
Notifications
You must be signed in to change notification settings - Fork 37
Extensibility Guide
The Python Environments extension is designed from the ground up to be extensible. Rather than trying to build comprehensive support for every Python tool in-house, the extension provides APIs that let anyone contribute environment managers, package managers, and project templates—appearing seamlessly alongside built-in functionality.
This guide explains the architecture, shows what's possible, and helps you get started building your own integration.
The Python ecosystem is vast and constantly evolving. New tools like uv, pixi, hatch, and pdm emerge regularly, each with their own communities and workflows.
We believe the people who know a tool best should decide how it integrates with VS Code. Rather than the Python extension team becoming experts in every environment manager, extensibility puts that power in the hands of:
- Tool maintainers who understand their tool's nuances and edge cases
- Community members who use specific tools daily and know what workflows matter
This approach means:
- Faster integration — new tools can appear in VS Code without waiting for Python extension releases
- Better quality — integrations are maintained by people who actually use the tools
- More tools supported — niche tools can get first-class support without competing for core team priorities
The extension has a pluggable architecture built around three main concepts:
┌─────────────────────────────────────────────────────────────┐
│ Python Sidebar UI │
│ ┌─────────────────────┐ ┌────────────────────────────┐ │
│ │ Python Projects │ │ Environment Managers │ │
│ └─────────────────────┘ └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Python Environments API │
│ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────┐ │
│ │EnvironmentManager│ │ PackageManager │ │ProjectCreator│ │
│ └──────────────────┘ └──────────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Built-in │ │ Community │ │ Your Extension │
│ venv, conda, │ │ pixi, hatch, │ │ │
│ pyenv, etc. │ │ etc. │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Key insight: The built-in managers (venv, conda, pyenv, etc.) use the exact same APIs available to external extensions. There's no special treatment—if we can build it, you can too.
An EnvironmentManager handles the lifecycle of Python environments:
| Capability | Description |
|---|---|
| Find | Discover existing environments on the system |
| Create | Create new environments (interactive or quick) |
| Remove | Delete environments |
| Resolve | Given a path, determine which environment (if any) is at that location |
Each manager has a unique ID in the format <publisher>.<extension>:<manager-name>, for example:
ms-python.python:venvms-python.python:condarenan-r-santos.pixi-code:pixi
A PackageManager handles installing and managing packages within an environment:
| Capability | Description |
|---|---|
| Install | Install packages (by name, from requirements file, etc.) |
| Uninstall | Remove packages |
| List | Show installed packages |
| Search | Find available packages |
Each environment manager declares a preferred package manager. For example, venv prefers pip, while conda prefers the conda package manager. Users can override this per-project.
A PythonProject associates a file or folder with a specific environment. Projects are created via PythonProjectCreator implementations, which can scaffold new project structures (like a package template with pyproject.toml and tests).
EnvironmentManager (1) ──creates──▶ (n) PythonEnvironment
EnvironmentManager (1) ──prefers──▶ (1) PackageManager
PackageManager (1) ──acts on──▶ (n) PythonEnvironment
PythonProject (1) ──uses────▶ (1) PythonEnvironment
The extension ships with support for these environment managers:
| Manager | Find | Create | Quick Create | Preferred Package Manager |
|---|---|---|---|---|
| venv | ✅ | ✅ | ✅ | pip |
| conda | ✅ | ✅ | ✅ | conda |
| pyenv | ✅ | — | — | pip |
| poetry | ✅ | — | — | poetry |
| pipenv | ✅ | — | — | pip |
| system | ✅ | — | — | pip |
See the full implementation in src/managers for reference.
- Node.js 22.x or later
- npm 10.x or later
- VS Code Extension development basics (VS Code Extension Guide)
Use the VS Code extension generator:
npm install -g yo generator-code
yo codeChoose "New Extension (TypeScript)" and follow the prompts.
In your package.json, add the Python Environments extension as a dependency:
{
"extensionDependencies": [
"ms-python.vscode-python-envs"
]
}Copy api.ts into your extension, then create a helper to access it:
// pythonEnvsApi.ts
import * as vscode from 'vscode';
import { PythonEnvironmentApi } from './api';
let _extApi: PythonEnvironmentApi | undefined;
export async function getEnvExtApi(): Promise<PythonEnvironmentApi> {
if (_extApi) {
return _extApi;
}
const extension = vscode.extensions.getExtension('ms-python.vscode-python-envs');
if (!extension) {
throw new Error('Python Environments extension not found.');
}
if (!extension.isActive) {
await extension.activate();
}
_extApi = extension.exports as PythonEnvironmentApi;
return _extApi;
}// extension.ts
import { ExtensionContext } from 'vscode';
import { getEnvExtApi } from './pythonEnvsApi';
import { MyEnvManager } from './myEnvManager';
export async function activate(context: ExtensionContext) {
const api = await getEnvExtApi();
const envManager = new MyEnvManager(api);
context.subscriptions.push(api.registerEnvironmentManager(envManager));
}Implement the EnvironmentManager interface. At minimum, you need:
-
id— unique identifier likeyour-publisher.your-ext:your-manager -
name/displayName— shown in the UI -
getEnvironments()— returns discovered environments -
resolve()— given a path, returns the environment if it matches your manager
Optional but recommended:
-
create()/supportsQuickCreate— for creating new environments -
remove()— for deleting environments
See built-in implementations for complete examples.
To build a great integration, it helps to understand how users interact with the extension:
- Making and Managing Python Projects — How users create and manage projects
- Interpreter Selection Quick Reference — How the extension chooses which environment to use
- Multi-Project Testing — How testing integrates with projects
- Full API types: src/api.ts
- Example extension: examples/sample1
- Built-in managers: src/managers
- Architecture deep dive: docs/design.md
- Discussions: GitHub Discussions
- Issues: GitHub Issues