/flags/poetry/poetry-directory-project
poetry -C (--directory) and -P (--project): run Poetry for another folder
- tool
- Poetry
- command
- poetry
- flag
- -C, --directory DIR; -P, --project DIR
- default
- the current directory (and its parents) is searched for pyproject.toml
Poetry looks for pyproject.toml in the current directory and its parents. poetry -C backend install (long form --directory) runs the command as if you had changed into backend/ first. Poetry 2 added -P (--project), which selects the project in backend/ but keeps resolving relative paths from where you are. Both are global options, so they go right after poetry, and both remove the need for cd backend && poetry ... in CI scripts and monorepos.
Outside the project, -C and -P
mkdir backend
cat > backend/pyproject.toml <<'EOF'
[project]
name = "backend"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = []
[tool.poetry]
package-mode = false
EOF
P="uvx -q poetry@2.5.1"
echo "--- poetry check (from the parent folder)"
$P check 2>&1 | sed -E 's#in .*/work.*#in <cwd> or its parents#'
echo "--- poetry -C backend check"
$P -C backend check
echo "--- poetry -P backend check"
$P -P backend check
echo "--- where commands run"
$P -C backend config virtualenvs.in-project true --local
$P -C backend run python -c "import os; print(os.path.basename(os.getcwd()))" 2>&1 | grep -v "^Creating virtualenv"
$P -P backend run python -c "import os; print(os.path.basename(os.getcwd()))"Output
--- poetry check (from the parent folder) Poetry could not find a pyproject.toml file in /tmp/work or its parents --- poetry -C backend check All set! --- poetry -P backend check All set! --- where commands run backend work
From the parent folder Poetry stops with the error explained in Poetry could not find a pyproject.toml file. Both options find the project. The last two lines show the difference: with -C the command runs inside backend, with -P it runs in the current folder (work here).
-C versus -P
| Aspect | -C, --directory | -P, --project |
|---|---|---|
| Available since | Poetry 1.8 (2024) | Poetry 2.0 (2025) |
| Finds pyproject.toml in | DIR | DIR |
| Working directory of poetry run | DIR | The current directory |
| Relative paths in arguments | Resolved from DIR | Resolved from the current directory |
| Typical use | Same as cd DIR, without changing the shell | Run project tools against files elsewhere |
CI and monorepos
poetry -C services/api install --only main
poetry -C services/api run pytest
poetry -P services/api run python scripts/migrate.py # script path relative to the repo rootThe same idea exists in other tools: yarn --cwd DIR (yarn --cwd), npm --prefix DIR, uv --directory DIR and cargo --manifest-path DIR/Cargo.toml.
Pitfalls
- Put the option before the command:
poetry install -C backendis rejected or misread by older versions;poetry -C backend installalways works. - With
virtualenvs.in-project = true, the.venvis created inside the project folder whichever option you use. - Poetry 1.7 and older have neither option; there, change into the folder first.
- A
poetry.tomlwith local settings is read from the project folder, so-Cand-Pboth pick it up.
FAQ
What is the difference between -C and -P in Poetry 2?
-C (--directory) makes Poetry behave as if you had run cd into the folder: the project and every relative path are resolved there. -P (--project) only selects the project; relative paths on the command line are still resolved from your current directory.
Does poetry -C change the directory for poetry run?
Yes. With -C the command runs as if started inside the folder, so relative paths in the command refer to that folder. With -P the command runs in your current directory.
Why does Poetry say it could not find a pyproject.toml file?
Poetry looks for pyproject.toml in the current directory and its parents. When you run it from elsewhere, point it at the project with -C or -P, or cd into the folder first.