Create a Python virtual environment — batteries included.
tn-venv is a zero-dependency, batteries-included replacement for python -m venv
that picks sensible defaults out of the box: running bare tn-venv creates ./.venv
with the current interpreter and pip already installed.
$ tn-venv
==> creating virtual environment at ./.venv
==> installing pip (ensurepip)
interpreter: cpython 3.14.7 (64-bit) from C:\Python314\python.exe
==> python binaries installed to ./.venv\Scripts
environment ready: .\.venv\Scripts\python.exe
activate with: .\.venv\Scripts\Activate.ps1 (PowerShell) | .\.venv\Scripts\activate.bat (cmd)tn-venv |
stdlib venv |
virtualenv |
|
|---|---|---|---|
| Zero runtime dependencies | ✅ | ✅ | ❌ |
Ships pip, setuptools, wheel after creation |
✅ | ❌ (3.12+) | ✅ |
| Generates activation scripts for bash / zsh / fish / csh / Nushell / PowerShell / cmd | ✅ | bash + PowerShell | 5 shells |
Discovers interpreters from PATH, registry, py launcher, uv, pyenv |
✅ | ❌ | partial |
| Pin or upgrade pip from the index | ✅ | ❌ | ✅ |
| Offline mode / extra wheel dirs | ✅ | ❌ | ✅ |
| Pure-Python, no compiled extensions | ✅ | ✅ | ❌ |
Ships activate_this.py |
✅ | ❌ | ✅ |
| Locking against concurrent creation | ✅ | ❌ | ❌ |
| One command, sensible defaults | ✅ | ❌ | ✅ |
Requires Python 3.11+.
pip install tn-venvOr directly from the repo:
pip install git+https://github.com/tokenoodle-everything/tn-venv.gitThis installs two console scripts:
tn-venvtn_venv(alias)
You can also invoke the CLI without installing anything:
python -m tn_venv .venvtn-venv --list-pythons
# Print the resolved configuration without creating anything
tn-venv --dry-run| Flag | Description |
|---|---|
-p SPEC / --python SPEC |
Python to build from — a path, a version (3, 3.12, 3.12.1), a name (python3.12, pypy3.10) or a PEP 514-ish tag. Repeatable; first match wins. Default: the interpreter running tn-venv. |
--list-pythons |
List every discoverable interpreter and exit. |
| Flag | Description |
|---|---|
--clear |
Delete the destination directory before creating. |
--upgrade |
Upgrade an existing environment in place (keep installed packages). |
--system-site-packages |
Give the environment access to the system site-packages. |
--symlinks / --no-symlinks |
Symlink the interpreter binaries (default on POSIX). |
--copies / --no-copies |
Copy the interpreter binaries (default on Windows). |
--scm-ignore {git,none} |
Write a source-control ignore file (default: git). |
| Flag | Description |
|---|---|
--seeder {pip,none} |
Package installer to seed the environment with (default: pip). |
--no-pip / --without-pip |
Skip pip installation. |
--pip [VERSION] |
Pip version to install. Omit value for the latest release (--pip ≡ --pip latest), pass a version to pin (--pip 24.0). |
--upgrade-pip |
Upgrade pip to the latest release from the package index. |
--setuptools [VERSION] |
Install setuptools (optionally pinned). Not bundled on Python ≥ 3.12. |
--wheel [VERSION] |
Install wheel (optionally pinned). |
--extra-search-dir DIR |
Additional directory to search for wheels/sdists (PIP_FIND_LINKS). Repeatable. |
--offline |
Don't reach the network; use only bundled wheels and --extra-search-dir (PIP_NO_INDEX). |
--with PKG / --seed-package PKG |
Install extra packages after seeding. Repeatable. |
-r FILE / --requirements FILE |
Install from a requirements file. Repeatable. |
| Flag | Description |
|---|---|
--activators NAMES |
Comma-separated activation scripts to generate. Names: bash, batch, powershell, fish, csh, nushell, python, plus all and default. Prefix with - to exclude (e.g. -fish). |
--prompt NAME |
Custom prompt shown when the environment is active (default: the environment folder name). |
| Flag | Description |
|---|---|
-q / --quiet |
Reduce verbosity (repeatable). |
-v / --verbose |
Increase verbosity (repeatable). |
--color / --no-color |
Force colored output on or off. Honors NO_COLOR and FORCE_COLOR. |
--dry-run |
Print the resolved configuration without creating anything. |
--config FILE |
Explicit path to a config file (overrides discovery). |
--no-config |
Ignore config files and environment variables. |
--version |
Print tn-venv version and exit. |
-h / --help |
Show help and exit. |
# One command: create ./.venv with pip and the current interpreter
tn-venv
# Pick a destination and a specific interpreter version
tn-venv .venv -p 3.12
# Let the environment see globally-installed packages
tn-venv /tmp/x --system-site-packagesConfiguration precedence (highest first):
- CLI flags — e.g.
tn-venv --clear TN_VENV_*environment variables — e.g.TN_VENV_CLEAR=1- Config file — discovered automatically, or via
--config FILE/TN_VENV_CONFIG_FILE - Built-in defaults
tn-venv walks the current directory and its parents (stopping at .git) looking for the first match:
pyproject.toml— only counts when it contains a[tool.tn-venv]or[tool.tn_venv]sectiontn-venv.initn_venv.ini.tn-venv.toml— top-level keyssetup.cfg— only when it has a[tn_venv]section
[tool.tn-venv]
python = ["3.12"]
prompt = "my-project"
system-site-packages = false
activators = "powershell,batch,-nushell"
with = ["requests", "click"]
upgrade-pip = true[tn-venv]
python = 3.12, 3.13
prompt = my-project
clear = yes
extra-search-dir = /srv/wheels
requirements = dev-requirements.txtEvery option has a TN_VENV_<NAME> env var (uppercased destination):
export TN_VENV_PYTHON=3.12
export TN_VENV_PROMPT=my-project
export TN_VENV_CLEAR=1
export TN_VENV_NO_PIP=0
export TN_VENV_ACTIVATORS=powershell,batchUse tn_venv.create_venv programmatically:
from tn_venv import create_venv
result = create_venv(
".venv",
python="3.12",
with_pip=True,
pip="24.0",
setuptools=True,
wheel=True,
packages=["requests", "click"],
requirements=["dev-requirements.txt"],
activators=["bash", "powershell"],
prompt="my-project",
quiet=True,
)
print(result.env_dir) # PosixPath('.venv')
print(result.exe) # PosixPath('.venv/bin/python')
print(result.bin_path) # PosixPath('.venv/bin')
print(result.site_packages) # PosixPath('.venv/lib/python3.12/site-packages')
print(result.prompt) # 'my-project'
print(result.activation_scripts)
print(result.seed.pip) # '24.0'