A tool for managing virtualenvs via a declarative config file
Project description
venvs is a tool for configuring, in a single file, a set of virtualenvs, which packages to install into each, and any binaries to make globally available from within.
It is a thin layer on top of uv, adding a declarative configuration format.
Installation
uv tool install venvs
uv must be installed and on your PATH.
Configuration
Create a file at ~/.local/share/virtualenvs/virtualenvs.toml (or wherever $WORKON_HOME points). Each entry declares a venv using one of three table types depending on intent:
# [tool.X]: install package X and link its console scripts.
# Defaults: install = ["X"], link = scripts declared by X.
[tool.black]
[tool.ruff]
[tool.jsonschema]
extras = ["format"] # → install jsonschema[format]
install = ["jsonschema-cli"] # additional packages (scripts not linked)
# [dev.X]: a venv tracking a local project checkout, converged via
# `uv sync`. Disk dir is `X-dev` and auto-linked scripts get a `-dev`
# suffix, so `[tool.X]` and `[dev.X]` coexist without colliding.
[dev.jsonschema]
project = "~/Development/jsonschema"
groups = ["test"]
# [venv.X]: the explicit/escape-hatch table. All keys, no smart defaults.
[venv.development]
install = ["pudb", "twisted"]
link = ["trial"]
[venv.app]
install = ["flask"]
python = "python3.12"
link = ["flask:flask-app"]
Running venvs converge creates each venv, installs (or syncs) the specified packages, and symlinks the named binaries into ~/.local/bin/.
[virtualenv.X] is also accepted as a back-compat alias for [venv.X].
Config Reference
[tool.X]
Sugar for uv tool install-style venvs: one published package, its scripts auto-linked.
- extras
Package extras for the primary package, e.g. ["format"] → installs X[format].
- install
Additional (companion) packages, like uv tool install ... --with. Their scripts are not auto-linked.
- install-bundle
List of bundle names to install (see Bundles below). Scripts from bundle packages are not auto-linked.
- python
Python interpreter to use (default: python3).
- link
Explicit override of the auto-discovered link list. Use "source:target" to rename. link = [] disables linking entirely.
- link-module
Modules to expose as python -m <module> wrappers.
- post-commands
Commands to run after converging.
[dev.X]
A venv backed by a local Python project (typically a checkout you are developing). Converged via uv sync against the project’s pyproject.toml / uv.lock. Disk dir is always X-dev.
- project (required)
Path to the project directory (supports $ENV_VAR and ~/ expansion).
- groups
PEP 735 dependency groups to install, e.g. ["test", "docs"].
- extras
Project extras to install, e.g. ["cli"].
- link, link-module, post-commands
As for [tool.X]. Auto-linked scripts get a -dev suffix on their targets; explicit link = [...] is used verbatim.
[venv.X]
The explicit table — use this when [tool.X] / [dev.X] don’t fit. All of: install (list of packages), requirements (list of requirements.txt files), install-bundle, python, link, link-module, post-commands.
Bundles
Bundles are reusable package groups, referenceable from [venv.X] and [tool.X]:
[bundle]
dev = ["pytest", "ruff", "mypy"]
[venv.myproject]
install = ["mypackage"]
install-bundle = ["dev"]
Usage
venvs converge
Converge the configured set of virtualenvs:
$ venvs converge
Specific virtualenvs can be targeted:
$ venvs converge myproject tools
Options:
- --fail-fast
Stop on the first failure (default: continue and report errors at the end).
- --dry-run
Print what would be done (orphan removals, creates, updates with the specific reason, skips) without making any changes. Exits 0 if the configuration is already converged, 2 if any changes would be made, and non-zero on error. Cannot be combined with --fail-fast.
- --link-dir <path>
Directory to symlink binaries into (default: ~/.local/bin).
- --root <path>
Root directory for virtualenvs (default: platform-specific, or $WORKON_HOME).
Converge is idempotent – if the configuration and Python version haven’t changed and the virtualenv is healthy, it is skipped. Virtualenvs that are no longer in the configuration are automatically removed along with their symlinks. Broken virtualenvs (e.g. from a deleted Python installation) are automatically recreated.
Virtualenvs are converged in parallel.
venvs find
Find virtualenv paths:
$ venvs find # print the root directory $ venvs find name myproject # print the virtualenv path $ venvs find name myproject python # print path to a binary
Releasing
Releases are managed via cargo-release:
$ cargo release 2026.5.1
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file venvs-2026.5.3.tar.gz.
File metadata
- Download URL: venvs-2026.5.3.tar.gz
- Upload date:
- Size: 42.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0c2c4c4fd68ed1d3ce181ed87f404a699d8827670d3e23e638a2bdf6bef3186
|
|
| MD5 |
b6620e0f90507793e66f6abfdaf394d5
|
|
| BLAKE2b-256 |
95a8e6ab8dea47515cb94a87c4bac87dfb8f70629644256da6f26c6fbf9ba20c
|
Provenance
The following attestation bundles were made for venvs-2026.5.3.tar.gz:
Publisher:
ci.yml on Julian/venvs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
venvs-2026.5.3.tar.gz -
Subject digest:
a0c2c4c4fd68ed1d3ce181ed87f404a699d8827670d3e23e638a2bdf6bef3186 - Sigstore transparency entry: 1521819446
- Sigstore integration time:
-
Permalink:
Julian/venvs@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Branch / Tag:
refs/tags/v2026.5.3 - Owner: https://github.com/Julian
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file venvs-2026.5.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: venvs-2026.5.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 907.7 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecb572df29fbc37ae31f881bfb070f4076614612b37c0d9f695b597ca2448477
|
|
| MD5 |
0e91a5962da20ccb2ede349970f5b367
|
|
| BLAKE2b-256 |
2c6f9f723444b638fa6859715b01a8d8f02cf2566db90b404898b075422d2a52
|
Provenance
The following attestation bundles were made for venvs-2026.5.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
ci.yml on Julian/venvs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
venvs-2026.5.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
ecb572df29fbc37ae31f881bfb070f4076614612b37c0d9f695b597ca2448477 - Sigstore transparency entry: 1521819475
- Sigstore integration time:
-
Permalink:
Julian/venvs@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Branch / Tag:
refs/tags/v2026.5.3 - Owner: https://github.com/Julian
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file venvs-2026.5.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: venvs-2026.5.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 904.9 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c38e6a47f1d0b3439a2b45a79f8c2698d0a5da3172bfd71d1b62fb2636ef655c
|
|
| MD5 |
f4641536a027ac7140887af927593db2
|
|
| BLAKE2b-256 |
0e59a7cdd527946b9be6a689d85fb35cfa102d0333ec90af57cb45e260b4782c
|
Provenance
The following attestation bundles were made for venvs-2026.5.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
ci.yml on Julian/venvs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
venvs-2026.5.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
c38e6a47f1d0b3439a2b45a79f8c2698d0a5da3172bfd71d1b62fb2636ef655c - Sigstore transparency entry: 1521819485
- Sigstore integration time:
-
Permalink:
Julian/venvs@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Branch / Tag:
refs/tags/v2026.5.3 - Owner: https://github.com/Julian
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file venvs-2026.5.3-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl.
File metadata
- Download URL: venvs-2026.5.3-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl
- Upload date:
- Size: 972.8 kB
- Tags: Python 3, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14ca23d6cbb5446dad7314ac22f2464d07444e10fcbaa0fbd4e0925f1fe543b1
|
|
| MD5 |
c153dc6614af5a7082693c7f61771a06
|
|
| BLAKE2b-256 |
2b6ca94c24d835878fe6cad183e1bd4d44bbcccc75e47d690bf7f1b65a59cc23
|
Provenance
The following attestation bundles were made for venvs-2026.5.3-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl:
Publisher:
ci.yml on Julian/venvs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
venvs-2026.5.3-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl -
Subject digest:
14ca23d6cbb5446dad7314ac22f2464d07444e10fcbaa0fbd4e0925f1fe543b1 - Sigstore transparency entry: 1521819490
- Sigstore integration time:
-
Permalink:
Julian/venvs@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Branch / Tag:
refs/tags/v2026.5.3 - Owner: https://github.com/Julian
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file venvs-2026.5.3-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: venvs-2026.5.3-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 835.1 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e0d68c0cf1e823f48f19c29eb3c79045a4c4a86a17d4cda23e9ad7cbe63093f
|
|
| MD5 |
a37c56756483e01ca32dca3590bc48d4
|
|
| BLAKE2b-256 |
d7f6aac4775cb5ebfb46e1e511dd9f36b33e45f78dd004f46dd37915b040d8db
|
Provenance
The following attestation bundles were made for venvs-2026.5.3-py3-none-macosx_11_0_arm64.whl:
Publisher:
ci.yml on Julian/venvs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
venvs-2026.5.3-py3-none-macosx_11_0_arm64.whl -
Subject digest:
5e0d68c0cf1e823f48f19c29eb3c79045a4c4a86a17d4cda23e9ad7cbe63093f - Sigstore transparency entry: 1521819462
- Sigstore integration time:
-
Permalink:
Julian/venvs@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Branch / Tag:
refs/tags/v2026.5.3 - Owner: https://github.com/Julian
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file venvs-2026.5.3-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: venvs-2026.5.3-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 874.4 kB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81bb740533afe6532c09fc05b637bdeb31c38387cf91b386b3ebf8ad42230ee3
|
|
| MD5 |
196ce166c7e6553100c114f421048be2
|
|
| BLAKE2b-256 |
0b831de03d1eca430dc30cbda285e686ab443e54ea37373c4979479dacbd41d4
|
Provenance
The following attestation bundles were made for venvs-2026.5.3-py3-none-macosx_10_12_x86_64.whl:
Publisher:
ci.yml on Julian/venvs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
venvs-2026.5.3-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
81bb740533afe6532c09fc05b637bdeb31c38387cf91b386b3ebf8ad42230ee3 - Sigstore transparency entry: 1521819452
- Sigstore integration time:
-
Permalink:
Julian/venvs@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Branch / Tag:
refs/tags/v2026.5.3 - Owner: https://github.com/Julian
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@3a2b510b5225df97ac767653f861b3d3a39147d6 -
Trigger Event:
push
-
Statement type: