You activated .venv, ran pip install -r requirements.txt, and everything works in your terminal. You open the same project in Cursor and every import lights up red. Pylance reports Import "fastapi" could not be resolved. The Composer suggests pip install fastapi even though it is already installed. The status bar shows Python 3.11.7 64-bit pointing at /usr/local/bin/python3 instead of .venv/bin/python. This is a Python-extension interpreter discovery problem — not a real package install issue — and it cascades into every other surface: linting, type checking, agent edits, and run-and-debug.
Common causes
Ordered by likelihood for venv detection failures.
1. Cursor picked the wrong interpreter on first open
The Python extension scans for interpreters at workspace open and caches the choice in .vscode/settings.json. If the venv was created after that first open — or under a non-standard path — the cached choice points at the system Python and never updates.
How to spot it: .vscode/settings.json has "python.defaultInterpreterPath" pointing at /usr/local/bin/python or /opt/homebrew/bin/python3 rather than .venv/bin/python.
2. Venv lives outside the workspace root
If your venv is at ~/.virtualenvs/myproj (virtualenvwrapper) or in a sibling directory, the extension’s auto-scan misses it. Only ./.venv, ./venv, ./env get auto-detected.
How to spot it: which python in the integrated terminal shows the right venv, but the status-bar interpreter does not list it as an option.
3. Poetry / PDM / Hatch / uv-managed venv
Tools like poetry and uv store venvs in centralized caches (~/.cache/pypoetry/virtualenvs/..., ~/.local/share/uv/python/...). Cursor’s Python extension picks them up only if the relevant plugin is enabled or the path is supplied explicitly.
How to spot it: poetry env info --path returns a path that does not appear in the interpreter picker.
4. Conda environment not activated in Cursor’s launcher
Conda envs need either Anaconda Python extension support enabled or a python.condaPath setting. Without it, the env appears with the wrong base prefix and imports fail.
How to spot it: conda info --envs shows your env, but in Cursor the interpreter list shows it as (base) even when you select the project env.
5. Shell PATH differs between Cursor and terminal
Cursor inherits PATH from the parent process that launched it (Finder, Dock, Spotlight). If you depend on .zshrc/.bashrc for venv activation, those rc files never run for the GUI process.
How to spot it: Open the integrated terminal — echo $PATH is missing the entries you set in .zshrc. A fresh Terminal.app shows them fine.
6. Workspace is multi-root and the active root has no Python config
In a multi-root workspace, each folder can have its own Python interpreter. The status bar reflects whichever folder owns the active editor file — flipping between files in different roots silently swaps interpreter.
How to spot it: Imports work in one file but not in another in the same Cursor window. Status-bar interpreter changes when you click between them.
Before you start
- Confirm the venv actually works:
source .venv/bin/activate && python -c "import fastapi"succeeds from a plain terminal. - Note your venv location and tool (raw
venv,virtualenv,poetry,pdm,uv,conda). - Record the current interpreter shown in the Cursor status bar — bottom right, click “Python”.
- Capture
.vscode/settings.jsonbefore edits.
Information to collect
- Output of
which pythonandpython --versionfrom Cursor’s integrated terminal. - Output of
poetry env info --pathoruv venv --pathif applicable. - Contents of
.vscode/settings.json(Python-related keys). - Status-bar interpreter path (full path, not just label).
- Pylance “Show language server output” log — look for
Selected interpreter:line. - Whether Cursor was launched from Finder, terminal
cursor ., or Spotlight.
Step-by-step fix
Ordered fastest to most thorough.
Step 1: Set the interpreter explicitly via the command palette
Cmd+Shift+P -> Python: Select Interpreter -> “Enter interpreter path…” and paste the absolute path:
/Users/you/proj/.venv/bin/python
This writes python.defaultInterpreterPath to .vscode/settings.json and triggers an analyzer restart. 80% of cases stop here.
If you do not see the path you want in the list, click “Enter interpreter path…” -> “Find…” and browse to it.
Step 2: Pin the interpreter in workspace settings
Open .vscode/settings.json and lock it in:
{
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python",
"python.terminal.activateEnvironment": true,
"python.analysis.extraPaths": ["${workspaceFolder}/src"]
}
Using ${workspaceFolder} keeps the path portable across machines. Commit this file so teammates inherit the choice.
Step 3: Fix PATH inheritance for GUI launches
If integrated-terminal echo $PATH is missing entries, the rc files are not loading. Two options.
Move PATH-setting lines out of .zshrc (interactive only) into .zprofile (login shells, which Cursor’s terminal uses):
# ~/.zprofile
export PATH="/opt/homebrew/bin:$HOME/.local/bin:$PATH"
Or launch Cursor from a terminal so it inherits the right environment:
cursor .
After either fix, restart Cursor entirely (not just reload window).
Step 4: For Poetry / uv / PDM, point Cursor at the managed venv
Get the path:
poetry env info --path
# or
uv venv --path
Then either select that path via Step 1, or configure the tool to create venvs in-project:
poetry config virtualenvs.in-project true
poetry env remove --all
poetry install
A .venv folder now appears in the workspace root and auto-detection works.
Step 5: For Conda, install the Anaconda Python extension and set conda path
In Cursor extensions, install “Python” (Microsoft) and ensure the Conda integration is enabled. Then:
{
"python.condaPath": "/opt/homebrew/Caskroom/miniforge/base/condabin/conda",
"python.defaultInterpreterPath": "/opt/homebrew/Caskroom/miniforge/base/envs/myproj/bin/python"
}
Activate via Cmd+Shift+P -> Python: Select Interpreter and pick the conda env explicitly.
Step 6: For multi-root workspaces, pin per folder
Each folder in a multi-root workspace can carry its own .vscode/settings.json. Add the pin to every Python folder:
{
"python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python"
}
Now switching between files no longer flips interpreters.
Verify
- Open a
.pyfile from the project. Status bar showsPython 3.x.x (.venv)or your tool’s name. - Type
import <pkg>for a package only present in the venv. No red squiggle. - Run
python -c "import sys; print(sys.executable)"in a debug session — output matches.venv/bin/python. - Ask Composer to “add a fastapi route” — it should not propose
pip install fastapiif it is already inrequirements.txt.
Long-term prevention
- Always create the venv before opening the project in Cursor for the first time.
- Commit
.vscode/settings.jsonwithpython.defaultInterpreterPathpinned. - Use
poetry config virtualenvs.in-project true(oruv venv .venv) so the venv lives at./.venvand gets auto-detected. - Put PATH-setting commands in
.zprofilenot.zshrcso GUI launches inherit them. - Add a
make setup/just setuptarget so new contributors get the venv at the standard path. - Run
python -c "import sys; print(sys.prefix)"as part ofpyteststartup; assert it matches.venvin CI.
Common pitfalls
- Selecting the interpreter once, then deleting and recreating the venv — the cached path now points at a non-existent binary. Re-select after
rm -rf .venv && python -m venv .venv. - Putting
python.defaultInterpreterPathin user settings instead of workspace settings — it leaks across projects. - Activating the venv in the integrated terminal and assuming Pylance now sees it. Pylance uses the configured interpreter, not the terminal’s active venv.
- Trusting the status-bar label alone — it can say
.venvbut actually point at a stale path. Verify withpython -c "import sys; print(sys.executable)". - Running
cursor .from a terminal where the venv is already activated and getting different behavior than launching from Finder. Standardize one launch method per machine. - Forgetting that conda envs need an extra
python.condaPathsetting beyond just the interpreter pin.
FAQ
Q: Composer keeps suggesting pip install for packages already installed.
The agent reads the interpreter Cursor has selected. Fix the interpreter first; the suggestions will stop. See also Cursor reads wrong file.
Q: I changed python.defaultInterpreterPath but nothing updated.
Pylance caches the analyzer state. Cmd+Shift+P -> Python: Restart Language Server, or just reload the window.
Q: My venv is at ~/.virtualenvs/myproj. Can I keep it there?
Yes — pin the absolute path in .vscode/settings.json. But moving to ./.venv per project is simpler and more portable.
Q: Tests pass in terminal but fail under Cursor’s test explorer.
The test runner uses Cursor’s configured interpreter, not your active terminal venv. Verify the interpreter pin matches what the terminal uses.