You’ve probably been there. You are knee-deep in a Python project, hacking away at a custom library you built, and every time you change a single line of code, you have to run pip install . all over again. It’s tedious. It’s a workflow killer. Honestly, it’s enough to make you want to switch to Go. But then someone mentions pip install -e . and suddenly, the clouds part.
Development mode. That’s what the -e stands for. It’s short for "editable."
When you run this command in the root of your project directory, you aren't actually copying files into your site-packages folder like a standard installation does. Instead, you are creating a symbolic link—a shortcut, basically—from your Python environment directly to your source code. If you change a function in your editor, those changes are live the second you hit save. No reinstalling. No headaches. Just code that works as you write it.
The magic behind the editable flag
Under the hood, pip install -e . is doing something clever with how Python looks for modules. Traditionally, when you install a package, pip takes your code and shoves a copy of it into a directory deep inside your virtual environment. If you edit your original source code after that, the "installed" version stays exactly the same because it's just a static snapshot.
Editable installs change the game by using a .pth file or a more modern "link" mechanism. Python’s site-packages directory gets a tiny file that says, "Hey, if someone asks for this package, don't look here; go look over in /Users/you/projects/my-cool-tool."
💡 You might also like: Lining up clip art: Why your designs still look amateur and how to fix it
It is essentially a pointer. Because of this, your environment stays synced with your heartbeat. You modify a docstring? It's updated. You add a new class? It's right there. This is the bedrock of "hot-reloading" for Python library development. Without it, you'd spend half your day watching progress bars.
Why the dot actually matters
The . at the end of the command isn't just decoration. In terminal speak, the dot refers to the current working directory. You are telling pip: "Look right here in this folder for a pyproject.toml or a setup.py file."
If you were sitting in your home directory and your project was in a folder called cool-app, you’d run pip install -e cool-app. But most devs navigate into the project folder first. Hence, the dot. It’s local. It’s immediate.
It’s worth noting that this command relies heavily on your project having proper metadata. Back in the day, we all used setup.py. Now, the industry has largely shifted toward pyproject.toml thanks to PEP 517 and 660. Whether you use Flit, Hatch, Poetry, or the classic Setuptools, pip install -e . generally knows what to do as long as your build system is defined.
Common pitfalls that trip up even senior devs
It isn't all sunshine and rainbows. I’ve seen teams lose hours because they didn't realize that while code changes are live, metadata changes are not.
If you add a new dependency to your project.dependencies list in pyproject.toml, the editable install won't magically go out and fetch that new library for you. You have to run the command again. The link to your source code is live, but the instructions for building the environment are only read when you actually execute the install command.
Another weird quirk? Entry points.
If you define a CLI tool—say you want a command called my-tool to run a specific function—that script wrapper is created during the installation process. If you rename that command or change the entry point in your config file, your terminal won't know until you re-run pip install -e ..
I once watched a senior engineer spend an entire afternoon debugging a "command not found" error because they changed their script name in setup.cfg but forgot to refresh the editable install. We’ve all been there. It’s a rite of passage.
Comparison: Regular install vs. Editable install
Let’s look at the difference in behavior.
In a regular pip install . scenario, pip builds a wheel of your project. It then unzips that wheel into site-packages. It’s clean. It’s what you want for production or CI/CD pipelines. It ensures that what you are testing is exactly what the user will get.
In an editable install, pip basically says, "I trust you." It maps the namespace of your package to your local folder. This is specifically for development. You should never use -e in a production Dockerfile or on a live server. Why? Because if you accidentally delete your source folder or move it, your production app breaks instantly. Plus, it introduces a level of environmental "drift" that makes debugging production issues a nightmare.
The "Src" layout debate
If you’re a fan of the "src" layout—where your code lives in src/my_package/ instead of just my_package/—you might wonder if pip install -e . still works.
Yes. In fact, it's often better.
The "src" layout forces you to use an editable install to even run your tests. This prevents a common Python mistake where you accidentally run tests against your local folder instead of the installed package. By using a "src" layout and -e, you ensure that your import paths are identical to what a real user would experience, but you still get the benefit of live editing.
Modern tools like pytest work beautifully with this setup. You can run your suite, see a failure, fix the code, and immediately run the test again without any "build" step in between.
Beyond the basics: Troubleshooting
Sometimes, the link breaks. Maybe you switched virtual environments. Maybe you changed your Python version from 3.10 to 3.12.
If you find that your changes aren't showing up, the first thing to check is pip list. Look for your package name. Next to it, in an editable install, you should see a file path rather than just a version number. If it shows a version number without a path, you’ve done a regular install by mistake.
To fix it:
pip uninstall your-package-namepip install -e .
Also, watch out for "ghost" installs. If you have the same package installed both normally and editably, Python might get confused about which one to import. Always clean out the old one before switching modes.
Real-world workflow: How the pros use it
Imagine you are contributing to a massive open-source project like pandas or requests. You don't just download the code and start hacking.
First, you fork the repo and clone it locally. Then, you create a virtual environment. The very next step is almost always pip install -e .. This allows you to run the project's own test suite against the changes you are making in real-time.
If you were working on a bug fix for a deep-learning library, you might have a Jupyter Notebook open in one window and your VS Code in another. Because of pip install -e ., you can tweak the underlying math in the library and just restart the notebook kernel to see the effect. It creates a tight feedback loop.
Is it going away?
With the rise of "locked" environments and tools like Poetry or PDM, some people wonder if the raw pip command is becoming obsolete.
Hardly.
Even if you use a high-level wrapper, they are all essentially doing an editable install under the hood when you are in "dev" mode. Understanding what pip install -e . does is like knowing how to drive a manual car—it gives you a fundamental grasp of how the machine works, even if you usually drive an automatic.
Actionable steps for your next project
Ready to clean up your workflow? Here is how to handle your next Python module properly.
First, stop putting your scripts in the root directory. Create a proper structure with a pyproject.toml.
Next, immediately create a virtual environment using python -m venv .venv. Activate it. Once you're inside, run pip install -e . before you write a single line of actual logic. This sets the stage.
If you’re working on multiple related packages—say a backend and a shared utility library—you can actually install both of them editably in the same environment. Just navigate to each folder and run the command. Now, when you update the utility library, the backend sees those changes instantly. It’s a powerful way to manage "monorepo" styles without the overhead of complex build tools.
Finally, keep an eye on your site-packages. If things start acting weird, go in there and look for those .pth files. Knowing they exist is 90% of the battle when it comes to debugging path issues.
Stop reinstalling your code. Start using the -e flag. Your keyboard (and your sanity) will thank you.