Skip to content

Extensibility Guide

Eleanor Boyd edited this page Feb 10, 2026 · 2 revisions

Extending the Python Environments Extension

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.

Why Extensibility Matters

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

Architecture Overview

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.

Core Concepts

Environment Managers

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:venv
  • ms-python.python:conda
  • renan-r-santos.pixi-code:pixi

Package Managers

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.

Python Projects

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

Relationships

EnvironmentManager (1) ──creates──▶ (n) PythonEnvironment
EnvironmentManager (1) ──prefers──▶ (1) PackageManager
PackageManager     (1) ──acts on──▶ (n) PythonEnvironment
PythonProject      (1) ──uses────▶ (1) PythonEnvironment

Built-in Support

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.

Getting Started

Prerequisites

Step 1: Create your extension

Use the VS Code extension generator:

npm install -g yo generator-code
yo code

Choose "New Extension (TypeScript)" and follow the prompts.

Step 2: Add the extension dependency

In your package.json, add the Python Environments extension as a dependency:

{
  "extensionDependencies": [
    "ms-python.vscode-python-envs"
  ]
}

Step 3: Get the API

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;
}

Step 4: Implement and register your manager

// 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));
}

Step 5: Build your manager

Implement the EnvironmentManager interface. At minimum, you need:

  • id — unique identifier like your-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.

Understanding the User Experience

To build a great integration, it helps to understand how users interact with the extension:

API Reference

Questions or Feedback?