# pypa/virtualenv — codebase unpack

> Canonical page: https://codevetter.com/unpack/virtualenv

This is a deterministic Repo Unpack scan of pypa/virtualenv — a structural map, not a review, security audit, or maintainer-endorsed description.

- Scanned commit: 571bc2041dae5ecbd250d82ec7ef482cfd3c3b69 (2026-10-02)
- Last upstream commit: release 21.14.5
- Generated by codevetter 1.15.0 on 2026-10-02
- 278 files scanned · 2.1 MB

Source inspection; upstream code and tests were not executed.

## Languages

- Python: 182 files
- YAML: 21 files
- JSON: 9 files
- Markdown: 9 files
- TOML: 4 files
- C: 2 files
- JavaScript: 2 files
- CSS: 1 files

## Repository structure

- src/ — 104 files
- tests/ — 77 files
- .github/ — 36 files
- docs/ — 27 files
- tasks/ — 20 files

Probable source entrypoint: `pyproject.toml` (inferred from the tree, not upstream docs)

## Source layout — src/

- src/virtualenv/ — 104 files

## Package

- pyproject.toml: virtualenv vvcs — 0 declared dependencies

## Structural health signals

Average score 8/10 across 96 files; 6 hotspots. These are deterministic review leads, not proof of a bug.

## Recent history

- 571bc2041dae (2026-10-02) release 21.14.5
- 5b9b7de4f2f8 (2026-10-03) Reset the embed update log when it cannot be read (#3376)
- 9fd48c89ad69 (2026-10-02) 🐛 fix(ci): dump stacks from a thread that holds the GIL (#3377)
- 5183a1066e58 (2026-10-02) 🎨 style: give every Final annotation its type (#3375)
- 288f13c7ae4f (2026-10-02) 🎨 style(test): mark prompt fixture locals Final (#3374)

## Overview

virtualenv creates isolated Python environments for developers and tools that need a reusable environment-building API. At commit 571bc2041dae5ecbd250d82ec7ef482cfd3c3b69, it combines interpreter discovery, platform-specific creation, cached installation of seed packages, and shell activation through four plugin groups. Its distinctive boundaries are the target environment, a persistent per-user cache, external python-discovery, and optional pip/PyPI subprocess and network operations.

## System map

The runtime is a Python CLI and library organized around a creation session. Discovery, creation, seeding, and activation are selected through installed package metadata. Persistent state lives in app-data folders, while generated environment files live under the chosen destination with a guarded adjacent redirect. Packaging supports wheels, source distributions, and a standalone zipapp.
- The console script targets virtualenv.__main__:run_with_catch; python -m virtualenv reaches the same wrapper, while the package exports cli_run and session_via_cli. — [pyproject.toml#L69-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L69-L77) [src/virtualenv/__main__.py#L71-L95](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/__main__.py#L71-L95) [src/virtualenv/__init__.py#L1-L10](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/__init__.py#L1-L10)
- build_parser discovers the interpreter before constructing CreatorSelector, SeederSelector, and ActivationSelector; Session.run executes create → seed → activate → final configuration write. — [src/virtualenv/run/__init__.py#L100-L118](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L100-L118) [src/virtualenv/run/session.py#L70-L92](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L70-L92)
- Builtin discovery delegates get_interpreter to python-discovery; local PythonInfo is a compatibility re-export, and python-discovery>=1.6 is a runtime dependency. — [src/virtualenv/discovery/builtin.py#L8-L28](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/builtin.py#L8-L28) [src/virtualenv/discovery/py_info.py#L1-L9](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/py_info.py#L1-L9) [pyproject.toml#L52-L60](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L52-L60)
- Creator entry points include CPython, PyPy, GraalPy, RustPython, and stdlib venv implementations; CreatorSelector filters them through can_create and aliases the first compatible VirtualenvBuiltin as builtin. — [pyproject.toml#L78-L100](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L78-L100) [src/virtualenv/run/plugin/creators.py#L33-L64](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/creators.py#L33-L64)
- AppDataDiskFolder separates interpreter JSON, downloaded wheel house, versioned installation images, update logs, and extracted zipapp resources; make_app_data chooses disk, read-only, or temporary storage. — [src/virtualenv/app_data/via_disk_folder.py#L78-L114](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/via_disk_folder.py#L78-L114) [src/virtualenv/app_data/__init__.py#L49-L72](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/__init__.py#L49-L72)
- Seeding integrates distlib script generation, pip download subprocesses, and PyPI JSON metadata; FromAppData installs images directly, whereas PipInvoke runs pip under the created interpreter. — [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L169-L177](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L169-L177) [src/virtualenv/seed/wheels/acquire.py#L138-L173](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/acquire.py#L138-L173) [src/virtualenv/seed/embed/pip_invoke.py#L26-L41](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/pip_invoke.py#L26-L41) [src/virtualenv/seed/wheels/periodic_update.py#L448-L465](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L448-L465)
- Hatchling and hatch-vcs build the package and generate version.py; the custom SbomBuildHook conditionally embeds a CycloneDX SBOM, and tox defines interpreter tests, documentation, typing, package checks, and zipapp builds. — [pyproject.toml#L1-L7](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L1-L7) [pyproject.toml#L201-L213](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L201-L213) [hatch_build.py#L223-L253](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/hatch_build.py#L223-L253) [tox.toml#L2-L29](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tox.toml#L2-L29)
- make_zipapp bundles hashed, locked pure-Python wheels and a custom import loader; release CI publishes distributions to PyPI and zipapp/SBOM assets to GitHub, then updates get-virtualenv. — [tasks/make_zipapp.py#L63-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tasks/make_zipapp.py#L63-L103) [tasks/make_zipapp.py#L127-L140](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tasks/make_zipapp.py#L127-L140) [tasks/__main__zipapp.py#L178-L188](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tasks/__main__zipapp.py#L178-L188) [.github/workflows/release.yaml#L126-L174](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/workflows/release.yaml#L126-L174)

## Feature catalog

The primary command builds an environment at a positional destination, with selectable interpreter and creation strategy. Users control seed packages, activation scripts, configuration sources, and cache maintenance. The library API returns a session for inspecting environment properties. Additional outputs include environment metadata, cache/VCS markers, and a provisional project discovery redirect.
- --python/-p accepts repeated paths, identifiers, or version specifiers and uses the first successful discovery; --try-first-with supplies preferred candidates, and the default specification is sys.executable. — [src/virtualenv/discovery/builtin.py#L36-L76](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/builtin.py#L36-L76) [docs/how-to/usage.rst#L23-L80](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/docs/how-to/usage.rst#L23-L80)
- Creation options include --creator, --copies/--always-copy, --symlinks, --system-site-packages, --clear, and --no-vcs-ignore; unsupported copy/link capabilities constrain available flags. — [src/virtualenv/run/plugin/creators.py#L66-L76](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/creators.py#L66-L76) [src/virtualenv/create/via_global_ref/api.py#L71-L108](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/api.py#L71-L108) [src/virtualenv/create/creator.py#L125-L143](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L125-L143)
- --seeder defaults to app-data with pip as an alternative; --no-seed/--without-pip disables seeding, and seed options select embed, bundle, none, or exact versions plus local search directories and downloads. — [src/virtualenv/run/plugin/seeders.py#L21-L39](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/seeders.py#L21-L39) [src/virtualenv/seed/embed/base_embed.py#L92-L148](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L92-L148) [pyproject.toml#L102-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L102-L103)
- setuptools defaults to none for targets >=3.12; --wheel and --no-wheel are deprecated no-ops, and enabled bundled seeders reject targets below the oldest bundled release, currently 3.9. — [src/virtualenv/seed/embed/base_embed.py#L35-L49](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L35-L49) [src/virtualenv/seed/embed/base_embed.py#L70-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L70-L89) [src/virtualenv/seed/embed/base_embed.py#L117-L140](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L117-L140) [src/virtualenv/seed/wheels/embed/__init__.py#L11-L54](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/embed/__init__.py#L11-L54)
- --activators selects a comma-separated subset, defaulting to all supported implementations; eight registered activators cover bash, batch, cshell, fish, nushell, powershell, Python, and xonsh, with --prompt customization. — [pyproject.toml#L70-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L70-L77) [src/virtualenv/run/plugin/activators.py#L18-L69](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/activators.py#L18-L69)
- Users can override options through VIRTUALENV_* variables or a [virtualenv] INI section, select VIRTUALENV_CONFIG_FILE, and configure --app-data, --read-only-app-data, --reset-app-data, or --upgrade-embed-wheels. — [src/virtualenv/config/env_var.py#L15-L33](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/config/env_var.py#L15-L33) [src/virtualenv/config/ini.py#L22-L47](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/config/ini.py#L22-L47) [src/virtualenv/run/__init__.py#L132-L162](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L132-L162)
- cli_run creates and returns a Session; session_via_cli constructs the session without running creation, exposing creator, interpreter, seeder, and activators for callers. — [src/virtualenv/run/__init__.py#L26-L82](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L26-L82) [src/virtualenv/run/session.py#L45-L68](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L45-L68) [docs/reference/api.rst#L7-L24](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/docs/reference/api.rst#L7-L24)
- Creation writes CACHEDIR.TAG and normally .gitignore; provisional --venv-redirect/--no-venv-redirect controls an adjacent .venv file, while CLI reporting offers verbosity, version, traceback, and a completion/package summary. — [src/virtualenv/create/creator.py#L229-L263](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L229-L263) [src/virtualenv/create/creator.py#L270-L288](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L270-L288) [src/virtualenv/run/__init__.py#L165-L191](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L165-L191) [src/virtualenv/__main__.py#L53-L91](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/__main__.py#L53-L91)

## Data flow

CLI arguments, environment variables, and INI values become a provenance-aware options namespace. Discovery yields PythonInfo, and the creator owns destination layout and environment metadata shared by seeders and activators. Wheels move through verification, cache selection, installation images, and generated console scripts. Update processes persist version history for later runs.
- VirtualEnvConfigParser resolves environment defaults before INI defaults, then argparse applies CLI values; VirtualEnvOptions records source provenance used to arbitrate copy versus symlink settings. — [src/virtualenv/config/cli/parser.py#L94-L144](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/config/cli/parser.py#L94-L144) [src/virtualenv/config/cli/parser.py#L24-L40](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/config/cli/parser.py#L24-L40) [src/virtualenv/create/via_global_ref/api.py#L54-L69](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/api.py#L54-L69)
- get_discover parses plugin selection and discovery-specific arguments; Discover.interpreter caches run() once, and Builtin passes specifications, preferred executables, app-data, and the supplied environment to external discovery. — [src/virtualenv/run/plugin/discovery.py#L16-L50](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/discovery.py#L16-L50) [src/virtualenv/discovery/discover.py#L23-L38](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/discover.py#L23-L38) [src/virtualenv/discovery/builtin.py#L68-L76](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/builtin.py#L68-L76)
- Describe maps target Python install paths to destination script_dir, purelib, and platlib; the same Creator object supplies these paths to seeding and activation. — [src/virtualenv/create/describe.py#L21-L47](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/describe.py#L21-L47) [src/virtualenv/run/session.py#L82-L92](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L82-L92) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L57-L68](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L57-L68)
- Creator.set_pyenv_cfg records interpreter home, implementation, versions, executable, command, and virtualenv version; PyEnvCfg.write normalizes only designated path keys and collapses line boundaries before UTF-8 output. — [src/virtualenv/create/creator.py#L241-L256](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L241-L256) [src/virtualenv/create/pyenv_cfg.py#L15-L23](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/pyenv_cfg.py#L15-L23) [src/virtualenv/create/pyenv_cfg.py#L53-L68](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/pyenv_cfg.py#L53-L68)
- get_wheel conditionally consults from_bundle before downloading; from_bundle combines embedded wheels, update history, and extra search directories, choosing a newer local candidate when compatible. — [src/virtualenv/seed/wheels/acquire.py#L66-L105](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/acquire.py#L66-L105) [src/virtualenv/seed/wheels/bundle.py#L25-L51](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/bundle.py#L25-L51) [src/virtualenv/seed/wheels/util.py#L21-L59](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/util.py#L21-L59)
- FromAppData retrieves wheels in threads, keys images by target release, installer class, and wheel stem, builds missing images under a file lock, and copies or links image contents into purelib before generating console scripts. — [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L59-L79](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L59-L79) [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L132-L159](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L132-L159) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L57-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L57-L89)
- Activation converts destination, environment name, prompt, bin name, and Tcl/Tk values into quoted substitutions; templates are replaced in one pass and written to bin_dir, using UTF-8 BOM for PowerShell. — [src/virtualenv/activation/via_template.py#L44-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/via_template.py#L44-L77) [src/virtualenv/activation/via_template.py#L84-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/via_template.py#L84-L103)
- Periodic updates persist started/completed timestamps and wheel histories in per-distribution JSON; subsequent bundle requests select eligible cached versions using one-hour CI and 28-day minor-release grace conditions. — [src/virtualenv/seed/wheels/periodic_update.py#L35-L75](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L35-L75) [src/virtualenv/seed/wheels/periodic_update.py#L145-L153](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L145-L153) [src/virtualenv/seed/wheels/periodic_update.py#L349-L356](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L349-L356) [src/virtualenv/app_data/via_disk_folder.py#L104-L114](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/via_disk_folder.py#L104-L114)

## Behavior traces

Source walks followed startup and selection, environment creation and cached seeding, activation, and persistent wheel updates. Startup performs repeated partial parsing because selected implementations contribute additional arguments. Creation has separate builtin and stdlib venv branches. Activation generates scripts that users subsequently source; updates can continue in a background process.
- Startup: run_with_catch → run → cli_run → session_via_cli → build_parser; build_parser configures reporting, loads app-data, handles maintenance commands, then obtains discover.interpreter before selecting creation components. — [src/virtualenv/__main__.py#L19-L31](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/__main__.py#L19-L31) [src/virtualenv/__main__.py#L71-L83](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/__main__.py#L71-L83) [src/virtualenv/run/__init__.py#L43-L75](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L43-L75) [src/virtualenv/run/__init__.py#L91-L118](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L91-L118)
- Interpreter selection: get_discover → plugin.add_parser_arguments → plugin(options) → Discover.interpreter → Builtin.run → get_interpreter; failed specifications fall through until one succeeds, otherwise build_parser raises RuntimeError. — [src/virtualenv/run/plugin/discovery.py#L37-L50](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/discovery.py#L37-L50) [src/virtualenv/discovery/discover.py#L32-L38](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/discover.py#L32-L38) [src/virtualenv/discovery/builtin.py#L21-L28](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/builtin.py#L21-L28) [src/virtualenv/run/__init__.py#L104-L108](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L104-L108)
- Builtin creation: Session._create → Creator.run → ViaGlobalRefVirtualenvBuiltin.create → ensure_directories → initial pyvenv.cfg write → applicable source.run calls → superclass patch installation; Creator.run then writes markers, rebuilds metadata, and considers the redirect. — [src/virtualenv/run/session.py#L76-L80](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L76-L80) [src/virtualenv/create/creator.py#L217-L227](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L217-L227) [src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py#L88-L111](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py#L88-L111) [src/virtualenv/create/via_global_ref/api.py#L110-L126](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/api.py#L110-L126)
- Stdlib creation branch: Venv.create calls create_inline when the target is the current system interpreter, otherwise create_via_sub_process → get_host_create_cmd → run_cmd; both avoid pip and then ensure library directories and apply shared-library support. — [src/virtualenv/create/via_global_ref/venv.py#L26-L32](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/venv.py#L26-L32) [src/virtualenv/create/via_global_ref/venv.py#L50-L86](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/venv.py#L50-L86)
- Cached seeding: Session._seed → FromAppData.run → _get_seed_wheels → get_wheel; acquisition threads try local resolution before a download fallback unless download was explicitly selected, then aggregate failures before installation. — [src/virtualenv/run/session.py#L82-L85](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L82-L85) [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L56-L61](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L56-L61) [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L87-L143](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L87-L143)
- Installation: installer_class chooses symlink only with --symlink-app-data and pip>=19.3; _build_wheel_image → has_image/build_image → validated extraction → generated metadata/RECORD → install → prior-version uninstall → image sync → console entry-point creation. — [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L145-L159](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L145-L159) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L57-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L57-L89) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L108-L129](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L108-L129) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L179-L185](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L179-L185)
- Bash activation: Session._activate → BashActivator.generate → replacements → instantiate_template → _generate writes bin/activate; sourcing it runs deactivate nondestructive, selects VIRTUAL_ENV, and prepends its bin directory to PATH, while deactivate restores saved state. — [src/virtualenv/run/session.py#L87-L92](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L87-L92) [src/virtualenv/activation/bash/__init__.py#L14-L27](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/bash/__init__.py#L14-L27) [src/virtualenv/activation/via_template.py#L44-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/via_template.py#L44-L77) [src/virtualenv/activation/bash/activate.sh#L10-L96](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/bash/activate.sh#L10-L96)
- Persistent update: from_bundle → periodic_update → handle_auto_update records a start and trigger_update launches do_update; _run_do_update downloads eligible wheels and writes completion/history, while --upgrade-embed-wheels invokes manual_upgrade before interpreter selection. — [src/virtualenv/seed/wheels/bundle.py#L29-L33](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/bundle.py#L29-L33) [src/virtualenv/seed/wheels/periodic_update.py#L80-L94](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L80-L94) [src/virtualenv/seed/wheels/periodic_update.py#L228-L269](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L228-L269) [src/virtualenv/run/__init__.py#L100-L129](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L100-L129)

## Testing signals

Tests and CI were inspected, not executed; their existence establishes intended checks, not passing results. The inspected suite uses pytest, coverage, mocks, parallel workers, Hypothesis properties, and separate tooling checks. Coverage includes CLI selection, discovery, cached seeding, redirects, digest handling, and extraction safety. This inventory is bounded, and inspected mocked network tests do not establish live service behavior.
- The configured test stack includes pytest, pytest-mock, randomly, rerunfailures, timeout, xdist, and subprocess coverage support; tox packages a wheel and runs coverage-driven pytest with parallel workers by default. — [pyproject.toml#L113-L132](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L113-L132) [tox.toml#L25-L55](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tox.toml#L25-L55)
- tests/conftest.py gates integration tests on --int and slow tests on --skip-slow, except its single-item early return; property tests are excluded by default and run through a dedicated tox environment. — [tests/conftest.py#L56-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/conftest.py#L56-L77) [pyproject.toml#L301-L311](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L301-L311) [tox.toml#L214-L228](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tox.toml#L214-L228)
- CLI tests assert help/version exits, logging setup behavior, and diagnostics for an unavailable discovery method; discovery tests exercise missing-candidate fallback, env/CLI ordering, and an absolute target overriding try-first hints. — [tests/unit/test_run.py#L11-L55](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/unit/test_run.py#L11-L55) [tests/unit/discovery/test_discovery.py#L26-L108](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/unit/discovery/test_discovery.py#L26-L108)
- test_app_data_pinning creates an environment with local pip 26.0.1 and checks pip list output; acquisition tests assert a second exact-version request reuses cached download history. — [tests/integration/test_run_int.py#L16-L35](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/integration/test_run_int.py#L16-L35) [tests/unit/seed/wheels/test_acquire.py#L207-L245](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/unit/seed/wheels/test_acquire.py#L207-L245)
- Cached-seeder tests run two simultaneous environment creations, aggregate injected image-build failures, and assert extraction rejects parent traversal and POSIX/Windows absolute archive entries. — [tests/unit/seed/embed/test_bootstrap_link_via_app_data.py#L223-L301](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/unit/seed/embed/test_bootstrap_link_via_app_data.py#L223-L301)
- Hypothesis properties assert pyvenv.cfg never invents keys and retains one line per key, while batch quoting properties cover dangerous syntax, line boundaries, literal percent signs, and preserved parentheses. — [tests/property/test_pyenv_cfg.py#L35-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/property/test_pyenv_cfg.py#L35-L77) [tests/property/test_batch_quote.py#L29-L72](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/property/test_batch_quote.py#L29-L72)
- Digest/TLS tests mock urlopen to cover matching and mismatching hashes, missing digests, retries, and insecure fallback opt-in; redirect tests cover auto/forced/disabled behavior and preserving foreign, undecodable, or directory targets. — [tests/unit/seed/wheels/test_periodic_update.py#L558-L665](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/unit/seed/wheels/test_periodic_update.py#L558-L665) [tests/unit/create/test_venv_redirect.py#L31-L149](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/unit/create/test_venv_redirect.py#L31-L149)
- Inspected CI defines OS/interpreter matrices, separate property/fuzz/tasks/type/zipapp jobs, combined coverage, and CodeQL/query tests; configured coverage fails below 76% and omits runtime activation/import-hook files, so these definitions are neither execution results nor exhaustive coverage. — [.github/workflows/check.yaml#L25-L63](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/workflows/check.yaml#L25-L63) [.github/workflows/check.yaml#L244-L364](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/workflows/check.yaml#L244-L364) [pyproject.toml#L328-L337](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L328-L337) [.github/workflows/codeql.yaml#L23-L39](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/workflows/codeql.yaml#L23-L39)

## Risk map

These are source observations and explicitly labeled hypotheses, not confirmed vulnerabilities. The important boundaries involve executing trusted interpreters/plugins, downloading executable packages, generating shell/configuration text, and deleting or overwriting filesystem state. Controls include strict download arguments, digest checks, extraction containment, and quoted substitutions. Cache reuse and subprocess environment handling deserve focused review because their behavior spans multiple invocations and processes.
- Registered entry points are loaded through e.load before implementation selection; the threat model explicitly trusts installed plugins and target interpreters running with the invoking user's rights. — [src/virtualenv/run/plugin/base.py#L20-L36](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/base.py#L20-L36) [.github/THREAT_MODEL.md#L48-L67](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/THREAT_MODEL.md#L48-L67) [src/virtualenv/create/via_global_ref/venv.py#L72-L86](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/venv.py#L72-L86)
- Filesystem effects extend beyond repository scope: --clear deletes the validated destination, --reset-app-data deletes the selected cache, default cache setup can migrate an old folder, and creation may write an adjacent .venv redirect. — [src/virtualenv/create/creator.py#L217-L227](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L217-L227) [src/virtualenv/create/creator.py#L270-L288](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L270-L288) [src/virtualenv/app_data/via_disk_folder.py#L65-L67](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/via_disk_folder.py#L65-L67) [src/virtualenv/app_data/__init__.py#L32-L46](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/__init__.py#L32-L46)
- Download arguments are allow-listed, but PyPI digest verification is skipped when PIP_INDEX_URL, PIP_EXTRA_INDEX_URL, or PIP_INDEX is nonempty; the heuristic explicitly does not inspect pip.conf, and local extra-search wheels are trusted without hashes. — [src/virtualenv/seed/wheels/acquire.py#L23-L34](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/acquire.py#L23-L34) [src/virtualenv/seed/wheels/acquire.py#L138-L173](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/acquire.py#L138-L173) [src/virtualenv/seed/wheels/acquire.py#L220-L231](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/acquire.py#L220-L231) [.github/THREAT_MODEL.md#L68-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/THREAT_MODEL.md#L68-L77)
- VIRTUALENV_PERIODIC_UPDATE_INSECURE enables an unverified TLS context after the normal metadata lookup fails; those metadata responses provide the expected downloaded-wheel SHA-256 and release dates. — [src/virtualenv/seed/wheels/periodic_update.py#L360-L368](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L360-L368) [src/virtualenv/seed/wheels/periodic_update.py#L379-L420](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L379-L420) [src/virtualenv/seed/wheels/periodic_update.py#L423-L465](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L423-L465)
- Downloaded wheels and installation images are reused from trusted app-data without re-verification; bundled verification is memoized by filename, and has_image accepts any nonempty image directory. — [.github/THREAT_MODEL.md#L62-L65](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/THREAT_MODEL.md#L62-L65) [src/virtualenv/seed/wheels/embed/__init__.py#L96-L108](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/embed/__init__.py#L96-L108) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L219-L220](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L219-L220) [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L156-L159](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L156-L159)
- PipInvoke debug logging formats the full subprocess environment through LogCmd; trigger_update launches without its supplied env mapping, and _run_do_update uses os.environ rather than that caller mapping. — [src/virtualenv/seed/embed/pip_invoke.py#L30-L37](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/pip_invoke.py#L30-L37) [src/virtualenv/util/subprocess/__init__.py#L13-L22](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/util/subprocess/__init__.py#L13-L22) [src/virtualenv/seed/wheels/periodic_update.py#L252-L257](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L252-L257) [src/virtualenv/seed/wheels/periodic_update.py#L329-L337](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L329-L337)
- Hypothesis: an interrupted image build or concurrent update-log writer can leave partial/shared state because image validity is only nonemptiness, JSON writes replace contents directly, and inspected update callers do not enter the store's available lock context. (inferred) — [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L71-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L71-L89) [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L219-L220](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L219-L220) [src/virtualenv/app_data/via_disk_folder.py#L150-L158](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/via_disk_folder.py#L150-L158) [src/virtualenv/seed/wheels/periodic_update.py#L88-L107](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/periodic_update.py#L88-L107)
- Hypothesis: attacker-modified existing distribution metadata could expand reseeding's deletion scope, since _uninstall_dist joins top_level.txt and RECORD paths to dist.parent and deletes them without an explicit containment check in this function; the documented model trusts destination files. (inferred) — [src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L187-L213](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/pip_install/base.py#L187-L213) [.github/THREAT_MODEL.md#L58-L65](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.github/THREAT_MODEL.md#L58-L65)

## Extension points

Installed Python entry points form the principal extension mechanism. Each stage has a selection adapter and an implementation interface, with interpreter capabilities constraining applicable choices. Creation can extend filesystem references and layouts, while seeding can replace installation strategy. Activators pair shell-specific classes with templates, and storage/build hooks provide additional internal seams.
- Plugins register under virtualenv.discovery, virtualenv.create, virtualenv.seed, or virtualenv.activate; installed metadata supplies CLI choices, and built-in entry-point values win duplicate names. — [docs/plugin/architecture.rst#L11-L24](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/docs/plugin/architecture.rst#L11-L24) [src/virtualenv/run/plugin/base.py#L20-L30](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/base.py#L20-L30) [pyproject.toml#L70-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L70-L103)
- Discovery plugins implement Discover.run and add_parser_arguments, consume VirtualEnvOptions, and expose a lazily cached interpreter; get_discover installs their CLI options before construction. — [src/virtualenv/discovery/discover.py#L18-L38](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/discover.py#L18-L38) [src/virtualenv/run/plugin/discovery.py#L37-L50](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/discovery.py#L37-L50)
- Creator plugins provide can_create metadata, add_parser_arguments, and create; CreatorSelector rejects the reserved builtin registration name, reports capability errors, and passes selected metadata into construction. — [src/virtualenv/create/creator.py#L97-L124](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L97-L124) [src/virtualenv/create/creator.py#L162-L165](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L162-L165) [src/virtualenv/run/plugin/creators.py#L33-L64](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/creators.py#L33-L64) [src/virtualenv/run/plugin/creators.py#L82-L92](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/creators.py#L82-L92)
- Builtin creator families extend sources, setup_meta, and _executables; PathRefToDest maps host resources to destinations, while ExePathRefToDest handles executable aliases and copy/link differences. — [src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py#L39-L85](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/builtin/via_global_self_do.py#L39-L85) [src/virtualenv/create/via_global_ref/builtin/ref.py#L125-L172](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/builtin/ref.py#L125-L172)
- Describe supplies interpreter-derived layout properties and can_describe; non-Describe creators receive a compatible describer, and Venv delegates noncallable layout attributes to it. — [src/virtualenv/create/describe.py#L29-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/describe.py#L29-L89) [src/virtualenv/run/plugin/creators.py#L87-L92](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/creators.py#L87-L92) [src/virtualenv/create/via_global_ref/venv.py#L94-L100](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/venv.py#L94-L100)
- SeederSelector constructs selected seeders and checks cannot_seed only when enabled; BaseEmbed exposes distribution_to_versions, and FromAppData selects CopyPipInstall or SymlinkPipInstall strategies. — [src/virtualenv/run/plugin/seeders.py#L44-L49](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/seeders.py#L44-L49) [src/virtualenv/seed/embed/base_embed.py#L54-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L54-L89) [src/virtualenv/seed/embed/via_app_data/via_app_data.py#L145-L148](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/via_app_data/via_app_data.py#L145-L148)
- Activator extensions participate through supports, add_parser_arguments, and generation; ViaTemplateActivator offers templates, quote, replacements, substitutions, and as_name overrides, illustrated by BashActivator's activate.sh → activate mapping. — [src/virtualenv/run/plugin/activators.py#L18-L26](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/activators.py#L18-L26) [src/virtualenv/run/plugin/activators.py#L49-L69](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/plugin/activators.py#L49-L69) [src/virtualenv/activation/via_template.py#L28-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/via_template.py#L28-L103) [src/virtualenv/activation/bash/__init__.py#L14-L27](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/bash/__init__.py#L14-L27)
- Internal factory seams include make_app_data's disk/read-only/temporary selection and the Hatch custom build hook; ReadOnlyAppData disables updates and overrides cache writes, while SbomBuildHook appends generated SBOM files only for supported wheel builds. — [src/virtualenv/app_data/__init__.py#L49-L72](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/__init__.py#L49-L72) [src/virtualenv/app_data/read_only.py#L15-L42](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/read_only.py#L15-L42) [pyproject.toml#L201-L204](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L201-L204) [hatch_build.py#L240-L253](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/hatch_build.py#L240-L253)

## Contributor handoff

Start with orchestration and the selected implementation rather than assuming the inventory reflects current ownership. Tests and CI were inspected, not executed, and the brief covers a bounded set of source paths. Preserve option provenance, cache/version boundaries, shell quoting, and platform-specific layout behavior when making changes. Execution, installation, and release commands require a later task that authorizes them.
- Read pyproject.toml, run/__init__.py, Session, and plugin selectors first: options are introduced through staged parsing, and creator, seeder, and activator objects are constructed only after final parsing. — [pyproject.toml#L69-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L69-L103) [src/virtualenv/run/__init__.py#L67-L118](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L67-L118) [src/virtualenv/run/session.py#L70-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/session.py#L70-L103)
- For discovery work, distinguish local adaptation from external implementation: Builtin forwards to python-discovery, and discovery/py_info.py only re-exports PythonInfo. — [src/virtualenv/discovery/builtin.py#L8-L28](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/builtin.py#L8-L28) [src/virtualenv/discovery/py_info.py#L1-L9](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/discovery/py_info.py#L1-L9) [pyproject.toml#L52-L60](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L52-L60)
- Do not treat session_via_cli as side-effect-free: it calls build_parser, which constructs app-data defaults and handles reset/upgrade commands; make_app_data can create or migrate cache directories. — [src/virtualenv/run/__init__.py#L67-L69](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L67-L69) [src/virtualenv/run/__init__.py#L100-L102](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L100-L102) [src/virtualenv/run/__init__.py#L132-L162](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/run/__init__.py#L132-L162) [src/virtualenv/app_data/__init__.py#L32-L72](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/app_data/__init__.py#L32-L72)
- Preserve provenance-aware precedence when changing flags: CLI outranks env, env outranks INI, and copy wins same-level conflicts; negative tri-state flags have special default handling. — [src/virtualenv/config/cli/parser.py#L101-L124](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/config/cli/parser.py#L101-L124) [src/virtualenv/config/cli/parser.py#L160-L166](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/config/cli/parser.py#L160-L166) [src/virtualenv/create/via_global_ref/api.py#L54-L69](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/api.py#L54-L69)
- For seeding edits, read BaseEmbed, acquisition, bundle selection, image installer, and embedded metadata together; preserve the >=3.12 setuptools default, wheel no-op deprecation, hash table, and target-version rejection. — [src/virtualenv/seed/embed/base_embed.py#L35-L89](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L35-L89) [src/virtualenv/seed/embed/base_embed.py#L117-L140](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/embed/base_embed.py#L117-L140) [src/virtualenv/seed/wheels/embed/__init__.py#L56-L108](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/embed/__init__.py#L56-L108) [src/virtualenv/seed/wheels/acquire.py#L80-L105](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/seed/wheels/acquire.py#L80-L105)
- For generated-file edits, preserve single-pass quoted template substitution and line-boundary collapse in pyvenv.cfg; retain the Python <3.10 import-hook gate and guarded foreign-redirect handling. — [src/virtualenv/activation/via_template.py#L84-L103](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/activation/via_template.py#L84-L103) [src/virtualenv/create/pyenv_cfg.py#L53-L68](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/pyenv_cfg.py#L53-L68) [src/virtualenv/create/via_global_ref/api.py#L113-L126](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/via_global_ref/api.py#L113-L126) [src/virtualenv/create/creator.py#L270-L288](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/src/virtualenv/create/creator.py#L270-L288)
- Tests and CI were inspected, not executed. In a later execution-authorized task, use an existing tox interpreter environment with a focused pytest path first, add --int for integration selection, and use separate property/tasks environments; configured CI jobs and thresholds are not passing results. — [tox.toml#L25-L55](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tox.toml#L25-L55) [tox.toml#L151-L187](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tox.toml#L151-L187) [tox.toml#L214-L228](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tox.toml#L214-L228) [tests/conftest.py#L63-L77](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/tests/conftest.py#L63-L77)
- Follow complete parameter/return annotations and future annotations, Ruff's 120-column configuration, and allowed Towncrier fragment types; distinguish verification from tox fix, whose pre-commit hooks can modify files with unsafe fixes. — [docs/development.rst#L100-L125](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/docs/development.rst#L100-L125) [pyproject.toml#L215-L219](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L215-L219) [pyproject.toml#L349-L356](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/pyproject.toml#L349-L356) [.pre-commit-config.yaml#L25-L52](https://github.com/pypa/virtualenv/blob/571bc2041dae5ecbd250d82ec7ef482cfd3c3b69/.pre-commit-config.yaml#L25-L52)

Source repository: https://github.com/pypa/virtualenv
Full evidence corpus: https://github.com/Codevetter/codevetter/tree/main/benchmarks/repo-unpacks/virtualenv.json

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
