How to manage Python environments with the uv SDK

The uv SDK is the recommended way to manage Python projects in Workshop. It ships uv and uvx, aliases pip to uv pip for compatibility, and exposes a virtual environment slot that other Python-based SDKs (such as jupyter) can plug into. The typical day-to-day flow boils down to running uv commands against a project virtual environment whose location you control.

Add the uv SDK to your workshop

Add - name: uv to the workshop definition; the SDK tracks the latest/stable channel by default, which is sufficient for most projects:

workshop.yaml
name: pyenv
base: ubuntu@24.04
sdks:
  - name: uv

Place your project at the host directory that you launch the workshop from; Workshop bind-mounts it inside the workshop at /project/. The project should contain a pyproject.toml (or a requirements.txt) that uv can read.

Run uv from your project

Open a shell in the workshop and use uv from /project/:

$ workshop shell
workshop@pyenv:~$ cd /project
workshop@pyenv:/project$ uv sync
workshop@pyenv:/project$ uv add requests
workshop@pyenv:/project$ uv run python -c "import requests"

uv sync resolves the project’s dependencies and creates a virtual environment at /project/.venv, that is, next to your pyproject.toml. uv run and uv add then operate against that environment. The venv lives on the host filesystem because /project/ is the bind mount, so it survives container refreshes and is visible to host-side tooling such as IDEs.

The uv SDK aliases pip to uv pip through update-alternatives; running pip install <PACKAGE> from a workshop shell transparently invokes uv pip install <PACKAGE>.

Inspect what the SDK configures

The SDK applies a few defaults so that uv works correctly with the workshop’s storage layout:

  • UV_LINK_MODE is set to copy in the workshop user’s environment because the persistent cache mount does not support hardlinks. You don’t need to set this yourself.

  • The uv package cache is persisted on the host through a mount interface plug that maps /home/workshop/.cache/uv/ to durable storage, so cached downloads survive workshop updates.

  • A shared virtual environment slot is exposed at /home/workshop/uv-venv/. This slot exists for cross-SDK sharing (see the next section); it is not the venv your project uses by default.

Share the environment with another SDK

To run a Python SDK such as JupyterLab against a uv-managed environment, add the jupyter SDK alongside uv and connect jupyter:venv to uv:venv explicitly in the workshop definition:

workshop.yaml
name: pyenv
base: ubuntu@24.04
sdks:
  - name: uv
  - name: jupyter
connections:
  - plug: jupyter:venv
    slot: uv:venv

An explicit connections: block is required: without it, jupyter:venv falls back to system:mount (the host directory Workshop provides as a default plug target) and the two SDKs don’t share an environment.

After workshop refresh, workshop connections --all confirms the wiring:

$ workshop connections --all

  INTERFACE  PLUG                SLOT                NOTES
  mount      pyenv/jupyter:venv  pyenv/uv:venv       -
  mount      pyenv/uv:cache      pyenv/system:mount  -

Packages that jupyter installs into its venv now land in the shared environment provided by uv, so jupyter and uv run see the same dependency set.

Pin the project venv with UV_PROJECT_ENVIRONMENT

By default, uv places the project virtual environment at .venv next to the pyproject.toml it discovers, which inside a workshop is normally /project/.venv.

Override this default with UV_PROJECT_ENVIRONMENT when you want a single, explicit venv location regardless of where in the project tree uv is invoked, or when several workshops share the same project directory and should reuse one venv.

For example, to place the venv at /project/pinned-venv instead of the default /project/.venv:

$ echo 'export UV_PROJECT_ENVIRONMENT=/project/pinned-venv' >> ~/.profile
$ exec bash -l
$ cd /project
$ uv sync

Relative paths are resolved from the workspace root, absolute paths are used as is; if the environment does not exist at the specified path, uv creates it.

Warning

Set UV_PROJECT_ENVIRONMENT to a path inside /project/, such as /project/.venv/, not to /project/ itself. uv writes the venv layout (bin/, lib/, pyvenv.cfg) directly under the value you provide, so a bare /project/ would scatter venv files across your project sources.

See also

Explanation:

How-to guides:

Tutorial: