Configuration files
This page is the normative reference for file-based configuration. For the narrative explanation and examples, see Configuration.
Discovery algorithm
If
--config FILEis given, use exactly that file (must exist).Else if
TN_VENV_CONFIG_FILEis set, use that file (must exist).Else, starting at the current working directory and walking up parent by parent, test the candidates below in order within each directory. After testing a directory that contains a
.gitentry, stop walking.The first candidate that qualifies becomes the config file. If none qualifies, no file layer is applied.
Order |
Candidate |
Qualifying condition |
Section read |
|---|---|---|---|
1 |
|
has |
that table |
2 |
|
exists |
|
3 |
|
exists |
same as above |
4 |
|
exists |
TOML top level |
5 |
|
has |
|
Malformed TOML/INI is a ConfigError (exit code 2). A pyproject.toml
without a tn-venv section is skipped — it never shadows a config file
higher up the tree.
Key mapping
Config keys match long-option names with dashes, and are normalized before
lookup (_ ≡ -, case preserved). Each key maps to the option of the same
name; CLI-only options (list-pythons, dry-run, config, no-config)
are not read from files.
Key |
Type |
Example |
|---|---|---|
|
list |
|
|
bool |
|
|
bool |
|
|
bool |
|
|
bool |
|
|
bool |
|
|
|
|
|
|
|
|
bool |
|
|
version string |
|
|
bool |
|
|
bool or version |
|
|
bool or version |
|
|
list |
|
|
bool |
|
|
list |
|
|
list |
|
|
list or string |
|
|
string |
|
|
integer |
|
|
integer |
|
|
bool |
|
Unknown keys are ignored, so shared files (notably pyproject.toml) may
contain other tools’ sections without errors.
Type coercion
TOML files provide native types; INI files provide strings and use the same
coercion as environment variables.
A TOML boolean given to a version-typed option (pip, setuptools,
wheel) means “unpinned”: setuptools = true ≡ --setuptools.
Complete example
# pyproject.toml
[tool.tn-venv]
python = ["3.12", "3.11"]
prompt = "billing-api"
system-site-packages = false
symlinks = true # on Windows, falls back to copies if symlinking fails
scm-ignore = "git"
seeder = "pip"
upgrade-pip = true
setuptools = true
wheel = true
with = ["pip-tools"]
requirements = ["requirements.txt", "dev-requirements.txt"]
activators = "bash,powershell"
verbose = 0