Python notebook environments with uv
Use a separate Python environment for an analysis when its notebooks need their own package versions. The uv prototype creates an environment in your analysis folder and registers it as a kernel you can select in JupyterLab. Several notebooks in the same folder can share that environment.
Before you start
Section titled “Before you start”Open a Terminal in Neurodesktop’s JupyterLab and run the commands as your normal
notebook user, without sudo. You need a recent Neurodesktop image with uv, the
image’s Python, and the Neurodesk kernel wrapper:
uv --version/opt/conda/bin/python -c 'import tomllib, jupyter_core'test -x /opt/neurodesktop/kernel_wrapper.shIf a check fails, use a newer Neurodesktop image before trying the prototype. The helper requires Python 3.11 or newer. Initial setup and installing new packages need access to the package index.
Choose a folder on persistent storage.
Use an analysis subfolder, such as ~/analyses/demo, rather than your home directory
or the root of a mounted drive. The prototype refuses existing unmanaged .venv
directories and projects inside uv workspaces; start with a fresh analysis folder
for your first trial.
Install the prototype helper
Section titled “Install the prototype helper”Download the helper from the tested recovery-fix commit (Neurodesktop PR #1263):
mkdir -p "$HOME/.local/share/neurodesk"curl --fail --location \ https://raw.githubusercontent.com/neurodesk/neurodesktop/587c607c7d4f10727b95bfe118f26197bf9c5917/config/jupyter/uv_kernel_prototype.py \ --output "$HOME/.local/share/neurodesk/uv-kernel-prototype.py"Keep this file at the same path while using its kernels. Each registration refers to this helper and the image’s Python interpreter.
Create an environment and select its kernel
Section titled “Create an environment and select its kernel”mkdir -p "$HOME/analyses/demo"/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ init "$HOME/analyses/demo"This creates or updates:
pyproject.toml, which declares the project’s dependencies.uv.lock, which records the resolved package versions..venv, which contains the project’s Python environment..neurodesk_uv_prototype.json, a local ownership record beside.venv.- A user kernel registration named Python (uv prototype: demo).
The helper records ipykernel as a development dependency. A new project uses
version 6.31.0, the compatibility version selected for this prototype. Running
init again reuses the registration rather than creating a duplicate. Existing
projects without uv.lock get a lockfile, including projects that already declare
ipykernel.
Open or create a notebook in the analysis folder. Click its kernel name and select Python (uv prototype: demo). If it is not listed, reload JupyterLab and reopen the kernel selector. Confirm the environment from a notebook cell:
import sysprint(sys.executable)The path should end in analyses/demo/.venv/bin/python. Selecting a kernel does not
move a notebook into that folder; save related notebooks alongside the project files.
Add Python packages
Section titled “Add Python packages”In the JupyterLab terminal, run:
uv add --project "$HOME/analyses/demo" numpy nibabelRestart the notebook kernel after changing packages. You can then import them in a cell:
import numpy as npimport nibabel as nibUse uv add to keep dependency changes in pyproject.toml and uv.lock. The
prototype does not install pip by default, so %pip install is not its supported
package-management workflow. Ad hoc installations would not update the lockfile.
Packages from Neurodesktop’s default Python environment are not automatically
available in this environment. For interactive widgets, add their Python packages
(for example, uv add --project "$HOME/analyses/demo" ipywidgets). Neurodesk’s
kernel wrapper still initializes its tool/module paths when the kernel starts.
Use Conda or Neurodesk containers when your
workflow needs software distributed through those systems.
Save and reproduce an analysis
Section titled “Save and reproduce an analysis”Keep your notebooks, pyproject.toml, and uv.lock together, and commit the latter
two files if you use Git. Do not commit .venv; it can be recreated and is tied to
its filesystem location. Keep .neurodesk_uv_prototype.json with the folder when moving it. This record
contains a local absolute path; keep it out of version control. It lives outside
.venv so uv can recreate the environment without losing ownership information.
Kernel registration is local to your Neurodesktop user and is not carried by the notebook or lockfile.
Preserve the helper and Jupyter’s user data directory across container replacement,
as well as your project folder. The default Jupyter data location is
~/.local/share/jupyter; installations can override it. Keeping uv’s cache and any
uv-managed Python installations persistent also avoids repeated downloads.
Kernel startup runs the prepared environment directly. It does not download packages, synchronize dependencies, or update the lockfile. After manually editing dependencies, synchronize explicitly before restarting your kernel:
uv sync --project "$HOME/analyses/demo" --locked --group dev--locked fails if the manifest and lockfile disagree. Prefer uv add for normal
package changes so both files stay in step.
Upgrade an older prototype installation
Section titled “Upgrade an older prototype installation”If you installed the original helper, repeat the download command above to replace
it at the same path. Shut down affected notebook kernels, then run init on each
project at its current location to migrate the ownership record:
/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ init "$HOME/analyses/demo"If uv recreated .venv after an interpreter change and the original helper now
reports Existing .venv is unmanaged, the updated helper can recover using the
project’s existing kernel registration. Run rebuild with the updated helper at
the original project path before moving the folder or removing its registration:
/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ rebuild "$HOME/analyses/demo"Recovery requires either a prototype ownership record or a matching registration, and the existing environment must be uv-created. The helper continues to refuse unmanaged and symlinked environments. Do not remove ownership records as a troubleshooting step.
Rebuild or move an environment
Section titled “Rebuild or move an environment”To recreate the environment from its existing manifest and lockfile:
/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ rebuild "$HOME/analyses/demo"A rebuild needs both pyproject.toml and uv.lock. It can work offline if the
required Python interpreter and packages are already available locally; a lockfile
alone does not contain those packages.
After moving the folder, rebuild at the new path and remove the old kernel
registration. For example, after moving demo to renamed-demo:
/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ rebuild "$HOME/analyses/renamed-demo"/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ remove "$HOME/analyses/demo"Select Python (uv prototype: renamed-demo) in each affected notebook. Old registrations continue to refer to the old path until removed.
Remove a registration
Section titled “Remove a registration”/opt/conda/bin/python "$HOME/.local/share/neurodesk/uv-kernel-prototype.py" \ remove "$HOME/analyses/demo"If no registration matches the path, the command reports No prototype registration and exits with status 1. Check the old path after a move rather than assuming its kernel was removed.
A successful removal deletes only the kernel registration. It retains notebooks, dependency files,
and .venv. Switch affected notebooks to another kernel. If you no longer use any
prototype kernels, you can also remove the downloaded helper.