Engineering Blog
BackThe Magic of uv within IntelliJ IDEA
Learn how to effectively use uv
package manager within IntelliJ IDEA for Python projects, with practical setup steps and workarounds for current limitations.
Recently, I took the time to delve into the uv package and project manager,
which you've likely heard of if you're involved in the Python community in any way. uv
is maintained by the
same company as the Ruff linter and code formatter. The command-line interface (CLI)
command felt fast and intuitive. But of course, I wanted to use IntelliJ IDEA for my project and
at the same time take advantage of uv
's features. This process was much less straightforward than I had expected,
since while there is uv
support in IntelliJ IDEA, it's currently not as well integrated as it could be.
That's why I have decided to write a blog post about how I currently set up my uv
-based projects,
primarily for my future self as a reference - but I guess it could also be helpful to others even if you
have no prior experience with uv
. In that sense, this blog is opinionated and just reflects my
current approach.
It's important to note that this is a snapshot, everything might change with future versions.
The Goal and Intro to this Guide
For me, these are the minimal requirements for a good development environment:
- No, or at least almost no, typing of commands into the terminal. Instead, I want to rely on Run Configurations and similar first-class IDE features.
- An exception to the above point is the initialization of a project, where I actually prefer the CLI.
- Imports must be correctly resolved within the IDE
- Debugger must work for the production as well as test code
- IDE is aware of the Python dependencies installed in the Project
If you want to follow along, please prepare the following:
- A
uv
binary in yourPATH
(see Installing uv) - An IntelliJ IDEA installation with the following plugins installed: Python and Python Community Edition. PyCharm should work as well, but I did not test it.
- Installed Python interpreter is optional, we'll use
uv
to set one up.
As of this writing the uv version I am using is 0.8.0
, together with IntelliJ IDEA 2025.2
and version
252.23892.458
of the two Python plugins.
Setting Up a Project with uv
In this section, we will set up a project with uv
and add some code. The goal is to see uv
and some
of its highlights in action.
Let's go ahead and create a new project. I pass the --package
flag to uv init
since I prefer to
use src-layout.
mkdir my-hello-project
cd my-hello-project
uv init --package
The working tree now looks like this:
.
|-- .git [truncated]
|-- .gitignore
|-- .python-version
|-- pyproject.toml
|-- README.md
`-- src
`-- my_hello_project
`-- __init__.py
Since this is pretty boring, let's add some code to the project, including two dependencies:
# Empty the __init__.py file
cat << EOF > src/my_hello_project/__init__.py
EOF
# Add some non-trivial code that requires a dependency
cat << EOF > src/my_hello_project/hello.py
import cowsay
import sys
import random
def run_hello() -> None:
characters = ["cow", "tux"]
random_char = random.choice(characters)
python_version, *_ = sys.version.split()
print(cowsay.get_output_string(random_char, f"Running on {python_version}"))
EOF
# Make my_hello_project a module
cat << EOF > src/my_hello_project/__main__.py
from my_hello_project.hello import run_hello
if __name__ == "__main__":
run_hello()
EOF
# Create tests
mkdir tests
cat << EOF > tests/test_hello.py
import sys
import pytest
from my_hello_project.hello import run_hello
def test_hello(capsys: pytest.CaptureFixture) -> None:
# act
run_hello()
# assert
major, minor, micro, *_ = sys.version_info
expected = f"{major}.{minor}.{micro}"
captured = capsys.readouterr()
assert expected in captured.out
EOF
Now we use uv
to add the two dependencies to pyproject.toml
:
uv add cowsay
uv add --dev pytest
And now we are ready for some action. Let's run the tests:
uv run -m pytest # or -m my_hello_project to run the application
The cool thing is that in this command multiple things happen:
- A python interpreter was downloaded if none was found in your
PATH
. - The
uv.lock
file that pins the exact versions of all dependencies was created. - A virtual env was created in
.venv
. - The dependencies were installed.
- An editable install of
my_hello_project
was created (seeuv pip freeze
). - The tests were run.
Running the Project from the IDE
Now let's get our project running smoothly from within the IDE! Here are my step-by-step instructions on how to run the project from the IDE:
Important: Do not confuse my-hello-project
(the name of the project) and my_hello_project
(the name of the package)
- Open the main
my-hello-project
directory from within IntelliJ IDEA. - Set up a Python SDK (Screenshot 1):
- Navigate to File > Project Structure > Project Settings > SDKs.
- Click the
+
button and selectAdd Python SDK from Disk
. - In the dialog, select the following values:
- Environment: Select Existing
- Type: uv
- Path to uv:
/path/to/your/uv
- Uv venv use:
/path/to/python3/in/your/.venv/directory
- Remember the name of the SDK you have just created.
- Set the SDK for the project (Screenshot 2):
- Navigate to File > Project Structure > Project Settings > Project
- Select the SDK you have just created in the SDK dropdown.
- Set the SDK for the module (Screenshot 3):
- Navigate to File > Project Structure > Modules > my_hello_project > Dependencies
- Select the SDK you have just created in the Dependency dropdown.
- Create a new Run Configuration (Screenshots 4 and 5):
- Navigate to Run > Edit Configurations
- Click the
+
button and selectPython
- Ensure the following values are set:
Use SDK of Module
:my-hello-project
module
:my_hello_project
- Add a "Before Launch" task:
- Click "Modify Options"
- Choose "Add before launch task"
- Choose "Run External tool" and click
+
: - Choose the following values and close the dialog:
- Name:
uv sync
- Program:
uv
- Arguments:
sync
- Working directory:
$ProjectFileDir$
- Name:
- Caveat: If your "Before Launch" task is not shown in the Run Configuration,
make sure to not only set the checkbox but also select the
uv sync
entry before clickingOK
.
Now you can use the Run Configuration to run the project as expected. You should see some ASCII art and the Python version printed in the Run Output.
_________________
| Running on 3.13.5 |
=================
\
\
^__^
(oo)\_______
(__)\ )\/\
||----w |
|| ||
Probably, you are wondering what the "Before Launch" task is for? uv sync
ensures that the
virtual environment is up to date and uses a Python version that matches the specifier in
.python-version
. Let's see that in action by switching to a different Python version (a pre-release
in this case):
echo '3.14.0b4' > .python-version
and run the Program again through the Run Configuration and you are now on the pre-release version:
___________________
| Running on 3.14.0b4 |
===================
\
\
\
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/
uv
as successfully upgraded the Python version used in the virtual env, even without us
thinking a single second about any CLI commands. Isn't that great? :-)
Setting up a Run Configuration for tests is straight forward, just right-click the tests
folder
and select "Run 'Python tests in tests'" and you are set (Screenshot 6). I'd suggest then also
adding a "Before Launch" task to run uv sync
as described above. An even better approach is
to the "Before Launch" task to the relevant Run/Debug Configuration Templates.
Epilogue: The "uv run" Run Configuration and Setting up an Entrypoint Script
You might have noticed that there's also a Run Configuration called "uv run." So, why did I opt for the lower level "Python" type with a "Before Launch" task to synchronize the virtual environment and execute the program? I faced two challenges:
- I only could get it to work in "Debug" mode, but not in "Run" (see also this issue).
- When upgrading to Python
3.14.0b4
it stopped working altogether.
But I guess that's just a matter of time and the issue will be resolved.
Finally, if your application is a CLI program, it's a good practice to set up an entrypoint script.
This allows users to run your program with a simple command when installed on their system.
For example, if you want your program to be callable by the name hello
, set up the following:
cat << EOF >> pyproject.toml
[project.scripts]
hello = "my_hello_project.hello:run_hello"
EOF
The program can now be run with uv run hello
. Or if you build and install it:
uv build
pipx install dist/*.whl
hello
If you have comments or corrections to share, you can reach our engineers at engineering-blog@cloudscale.ch.