Skip to main content

notuv — deprecated

notuv is deprecated. Use veneer instead:

uv tool install veneer-py
veneer <same arguments>

veneer is a drop-in replacement. Rename notuv.toml → veneer.toml and change [notuv] → [veneer].


Editable Python installs in git worktrees without copying heavy dependencies.

notuv runs commands inside a shared conda environment with a git-worktree-local .venv overlay. Use it when conda owns the heavy dependency stack and each worktree needs its own editable Python installs.

Why

If you have ever used Git worktrees for deep learning, you might be familiar with the following problem:

You are working on your project as an editable package installed locally, you have a conda env with big heavy packages like PyTorch and CUDA, and then you make a new git worktree to work on a feature in parallel.

You run your code and it does not behave as expected, because the editable Python package was still pointing to your original repo, not the new worktree. Ouch.

So now you either have install the worktree as an editable package, which breaks your original repo!

Or you can set PYTHONPATH= each time you run a command! Ew!

Or you can just set up a new conda env to stay sane, but then after 3 worktrees you have 25GB of conda envs on your machine!

notuv solves this specific problem:

  • one shared conda env owns the heavy dependency stack
  • each worktree gets a tiny .venv overlay for its editable installs
  • notuv.toml says which conda env and editable packages belong to that worktree
  • notuv <command> runs inside the conda env, then puts the worktree .venv first

notuv keeps the split explicit:

  • conda env: heavy shared dependencies
  • worktree .venv: editable local packages and console scripts
  • notuv.toml: the worktree's configuration

You do not need to conda activate the shared environment before running notuv commands. notuv reads notuv.toml, applies the configured conda environment to the child process, and keeps the worktree .venv/bin first on PATH.

Install

From PyPI:

python -m pip install notuv

For development from this checkout:

python -m pip install -e ".[dev]"

Check the command:

notuv --help

Quick Start

Create one shared conda environment that has your normal dependencies, but not the editable package you are developing:

conda create -n myproject-shared python=3.11 pip -y
conda run -n myproject-shared python -m pip install -U pip

For a real project, this is where you install PyTorch, CUDA-related packages, MuJoCo, Isaac Sim, or whatever heavy dependencies the project needs.

In a git worktree, add notuv.toml at the git root:

[python]
base_conda_env = "myproject-shared"

[editables]
packages = [
  ".",
]

Create the worktree .venv and install configured editables:

notuv update-editables

Run commands through the worktree environment:

notuv python -c "import sys; print(sys.executable)"
notuv pytest
notuv python scripts/example.py

These commands do not require conda activate myproject-shared first. The configured conda env still supplies native libraries, activation-script environment variables, and shared dependencies.

Verify that your editable package is imported from the current worktree:

notuv python -c "import your_package; print(your_package.__file__)"

Worktree-Local Config

If notuv.toml is local machine config, ignore it with the git worktree's exclude file. In git worktrees, .git may be a file, so use git rev-parse:

EXCLUDE="$(git rev-parse --git-path info/exclude)"
mkdir -p "$(dirname "$EXCLUDE")"
printf '\n# Local notuv config\n/notuv.toml\n/.venv/\n' >> "$EXCLUDE"

If notuv.toml should be shared by the team, commit it instead and only ignore .venv/.

Multiple Editable Packages

One worktree can own an environment for several local packages:

[python]
base_conda_env = "myproject-shared"

[editables]
packages = [
  ".",
  "../some-sibling-package",
  "~/Projects/repos/some-canonical-package",
  "../another-sibling-package",
]

Relative editable paths are resolved from the git root. Editable paths may also use absolute paths or ~, which is useful for canonical shared checkouts such as ~/Projects/repos/IsaacLab. The .venv path defaults to .venv and must stay inside the git root.

Explicit Stack Configs

Several repos can share one dependency stack when they belong to the same local development context. Keep that relationship explicit with a small repo-local pointer config:

worksets/my-feature/
  notuv.backend.toml
  .notuv/backend/.venv

  api-service/
    notuv.toml

  worker-service/
    notuv.toml

The shared stack config owns the base conda env, venv, and editable packages:

# worksets/my-feature/notuv.backend.toml
[notuv]
kind = "stack"

[python]
base_conda_env = "backend-shared"
venv = ".notuv/backend/.venv"

[editables]
packages = [
  "api-service",
  "worker-service",
  "~/Projects/repos/shared-library",
]

Each repo opts into that stack explicitly:

# worksets/my-feature/api-service/notuv.toml
[notuv]
extends = "../notuv.backend.toml"

Run commands from the repo you are working in:

cd worksets/my-feature/api-service
notuv info
notuv update-editables
notuv pytest

Commands run from the active repo root, while relative paths in the stack config resolve from the stack config directory. A workset can have more than one stack config when repos need different base conda environments.

Stack venvs may be shared by several repos. notuv clean refuses to remove a shared stack venv unless you say so explicitly:

notuv clean --shared

Commands

Show configuration without creating .venv:

notuv info

Create .venv if needed and install configured editables:

notuv update-editables

Run normal commands inside the configured conda env, with .venv/bin first on PATH:

notuv python -m pytest
notuv pytest
notuv my-console-script --help

Remove the worktree .venv:

notuv clean

Remove a shared stack .venv:

notuv clean --shared

Editable Installs

Editable installs are configured in notuv.toml, not through ad hoc pip commands.

These intentionally fail:

notuv pip install -e .
notuv pip install --editable ../some-package
notuv python -m pip install -e .

Use this instead:

[editables]
packages = [
  ".",
  "../some-package",
]
notuv update-editables

By default, update-editables uses pip install --no-deps -e ... because the base conda environment is expected to own dependencies. If a repo really needs editable dependencies installed into .venv, set:

[editables]
install_deps = true
packages = ["."]

Config Reference

Repo-local config:

[python]
base_conda_env = "myproject-shared"
venv = ".venv"

[editables]
packages = ["."]
install_deps = false

Pointer config:

[notuv]
extends = "../notuv.backend.toml"

Stack config:

[notuv]
kind = "stack"

[python]
base_conda_env = "backend-shared"
venv = ".notuv/backend/.venv"

[editables]
packages = ["api-service", "worker-service"]
install_deps = false

Fields:

  • notuv.extends: optional path from a repo-local pointer config to one stack config.
  • notuv.kind: set to "stack" in stack configs.
  • python.base_conda_env: required conda environment name.
  • python.venv: optional virtual environment path. Defaults to .venv. In repo configs, it must stay inside the repo root. In stack configs, it must stay inside the stack config directory. Absolute paths are accepted only when they remain inside the allowed root.
  • editables.packages: editable package paths. Relative paths resolve from the config file that declares them. Absolute paths and ~ are also accepted.
  • editables.install_deps: whether pip should install dependencies while installing editables. Defaults to false.

Troubleshooting

If notuv is not found, install it in the active Python environment:

python -m pip install --upgrade notuv

If notuv says missing notuv.toml, make sure you are inside a git worktree and that notuv.toml exists at the git root:

git rev-parse --show-toplevel

If imports come from the wrong place, check the active paths:

notuv info
notuv python -c "import your_package; print(your_package.__file__)"

If .venv gets stale, remove and recreate it:

notuv clean
notuv update-editables

Unsupported By Design

Version 1 does not support uv-managed environments, non-conda base environments, or automatic dependency solving. Those can be added later if the conda-backed overlay workflow proves useful.

Metadata

Release files for notuv 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for notuv 0.2.0
File Size Uploaded Provenance
notuv-0.2.0.tar.gz 39.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for notuv 0.2.0
File Interpreter ABI Platform
notuv-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 50.4 kB

Release files / notuv-0.2.0.tar.gz

Download URL notuv-0.2.0.tar.gz
Size 39.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e7dcfc43fef25a0fcaa6d504f7358be301b1eaa73f762bed44f2eaa6b4decf02
BLAKE2b-256 checksum
How to use checksums
5e740f50a47f001c6d35f17ae1b30fe7272fb5e7f7c6849b7e8a22107db0ffba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.

Transparency log

Release files / notuv-0.2.0-py3-none-any.whl

Download URL notuv-0.2.0-py3-none-any.whl
Size 10.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
63b1a8107bffb925fbc2f452cc71d8fa71ba511fed53eb47e23e8a82c02a865a
BLAKE2b-256 checksum
How to use checksums
0c808981063211dbe8104614a502f34f80aa8ce91ca60fdf7c9d291e1ace27c0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.

Transparency log

Security for notuv 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for notuv-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 11, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page