/config/poetry/virtualenvs-in-project
Poetry virtualenvs.in-project: create .venv inside the project
- tool
- Poetry
- file
- poetry.toml (project, with --local) or Poetry's config.toml (user)
- key
- virtualenvs.in-project
- type
- boolean (true, false) or unset
- default
- unset (null): .venv is used if it already exists, otherwise the env goes to the cache directory
virtualenvs.in-project controls where Poetry creates a project's virtual environment. Set it to true and Poetry creates it as .venv in the project root, next to pyproject.toml, which editors such as VS Code and PyCharm detect automatically. When it is unset (the default), Poetry uses an existing .venv if there is one, and otherwise creates the environment under its cache directory with a generated name like demo-AbC12xyZ-py3.13.
Set it
P="uv run -q --no-project --python 3.13 --with poetry==2.* poetry"
$P init -n --name demo >/dev/null
echo "default: $($P config virtualenvs.in-project)"
$P config virtualenvs.in-project true --local
echo "--- poetry.toml"
cat poetry.toml
echo "now: $($P config virtualenvs.in-project)"
echo "env var wins: $(POETRY_VIRTUALENVS_IN_PROJECT=false $P config virtualenvs.in-project)"Output
default: null --- poetry.toml [virtualenvs] in-project = true now: true env var wins: false
In the example Poetry runs through uv run --with poetry; with Poetry installed, the commands are poetry config virtualenvs.in-project true --local and so on.
Scopes
| How | Where it is stored | Applies to |
|---|---|---|
| poetry config virtualenvs.in-project true --local | poetry.toml in the project | This project (commit it to share the setting) |
| poetry config virtualenvs.in-project true | Poetry's user config.toml | Every project of this user |
| POETRY_VIRTUALENVS_IN_PROJECT=true | Environment | Commands run with that variable; overrides both files |
| poetry config virtualenvs.in-project --unset | (removes the setting) | Back to the default |
Move an existing environment into the project
Changing the setting does not move an environment Poetry already created. Remove the old one and install again:
poetry env list # environments of this project
poetry env remove --all # delete them
poetry install # creates .venv in the projectAdd .venv/ to .gitignore. Check where the active environment lives with poetry env info --path.
Related settings
| Setting | Default | What it controls |
|---|---|---|
| virtualenvs.create | true | Whether Poetry creates an environment at all; false installs into an active or existing one, or the system Python |
| virtualenvs.in-project | unset | Create the environment as .venv in the project root |
| virtualenvs.path | {cache-dir}/virtualenvs | Where environments go when they are not in the project |
| virtualenvs.prompt | {project_name}-py{python_version} | Prompt shown when the environment is activated |
| virtualenvs.options.system-site-packages | false | Give the environment access to the system site-packages |
| virtualenvs.use-poetry-python | false (Poetry 2.0+) | Use the Python Poetry was installed with instead of the active one |
Each setting has an environment variable with the POETRY_ prefix, upper case and underscores, such as POETRY_VIRTUALENVS_CREATE.
Why use .venv in the project
- Editors find it. VS Code, PyCharm and most language servers look for
.venvin the workspace and select it without configuration. - Docker and CI caches. A predictable path is easy to cache between CI runs or to copy between Docker build stages.
- Cleanup is obvious. Deleting the project folder deletes the environment; nothing is left behind in the cache.
The trade-off: tools that scan the project (linters, file watchers, backup tools) must ignore .venv, and a project folder synchronised by a cloud drive will also synchronise thousands of package files.
FAQ
Where does Poetry put the virtualenv when in-project is not set?
Under {cache-dir}/virtualenvs, with a name built from the project name, a short hash and the Python version. poetry env info --path prints the exact location.
I set in-project to true but Poetry still uses the old environment. Why?
A virtualenv already created in the cache directory keeps being used. Remove it with poetry env remove --all (or the specific environment) and run poetry install again to get .venv in the project.
Should I commit poetry.toml?
Commit it if it only holds project-wide settings such as virtualenvs.in-project, so everyone gets .venv in the same place. Do not put credentials in it.