.venv after opening files in a new worktree — no Claude Code restart required.
The Problem
With Claude Code’s official pyright plugin:- Create a worktree:
git worktree add ../my-project-worktree feat/new-feature - Open files in the worktree (no
.venvexists yet) - Create
.venv:cd ../my-project-worktree && uv sync - LSP doesn’t work — pyright still thinks there’s no venv
- Must restart Claude Code to pick up the new
.venv
Typical Worktree Workflow
Here’s the real-world scenario from the README:1
Create worktree
my-project-worktree/ has no .venv.2
Open files in Claude Code
Open
my-project-worktree/src/main.py in Claude Code.What happens:- typemux-cc searches for
.venvin parent directories - Finds none (stops at git toplevel)
- Caches
venv=Nonefor this document - LSP requests return errors (strict venv mode)
3
Create .venv
.venv exists:4
Reopen the file
Close and reopen
my-project-worktree/src/main.py.What happens:textDocument/didOpentriggers a fresh.venvsearch- typemux-cc finds
my-project-worktree/.venv - Spawns a new backend with
VIRTUAL_ENV=my-project-worktree/.venv - Restores the document to the new backend
- LSP features now work
No Claude Code restart required. The backend pool dynamically adds the new worktree’s backend.
Detection Logic
Git Toplevel as Search Boundary
typemux-cc caches the git repository root at startup:.venv:
Why use git toplevel?
Prevents searching outside the project. Without a boundary, typemux-cc might find
.venv from a parent project (e.g., system-wide venv), which would be incorrect.Worktree-Specific Behavior
Each worktree is a separate git working directory with its own.venv:
git rev-parse --show-toplevel in a worktree, it returns the worktree’s root (not the main repo root). This ensures .venv search is scoped correctly.
Late .venv Creation Scenario
Why the Cache Limitation Exists
venv field is set once when the document is opened. Subsequent LSP requests reuse this cached value without re-searching the filesystem.
Rationale: Filesystem I/O (checking for .venv/pyvenv.cfg) on every hover/completion request would be prohibitively expensive.
Workaround: Reopen Files
Closing and reopening a file clears its cache entry:didOpen triggers a fresh search:
Real Workflow Example
Here’s a complete workflow from a real AI-assisted development session:Multiple Worktrees
You can have multiple worktrees open simultaneously, each with its own.venv and backend:
- Open file from
my-project/→ backend spawned (session 1) - Open file from
my-project-feat-a/→ new backend spawned (session 2) - Open file from
my-project-feat-b/→ new backend spawned (session 3) - Return to
my-project/→ session 1 still in pool, no restart
TYPEMUX_CC_MAX_BACKENDS, default 8).
Troubleshooting
.venv not detected after creation
1
Verify pyvenv.cfg exists
2
Check git toplevel
3
Reopen files
Close all Python files in the worktree and reopen them. This clears cached
venv=None.4
Check logs
Still getting “venv not found” errors after reopening
Possible causes:- Symlink .venv: typemux-cc may not follow symlinks. Use an actual directory.
- Wrong .venv name: Only
.venvis supported (notvenv,.env, etc.). - Missing pyvenv.cfg: Some tools (conda) don’t create this file.
Worktree uses wrong venv (parent project’s venv)
This happens if git toplevel detection fails. Check:my-project-worktree, not my-project.
If returning the wrong path, your worktree setup is broken:
Summary
Worktree workflow checklist
- ✅ Create worktree:
git worktree add ../my-project-feat feat/new - ✅ Open files in Claude Code (LSP won’t work yet)
- ✅ Create venv:
cd ../my-project-feat && uv sync - ✅ Verify pyvenv.cfg:
cat .venv/pyvenv.cfg - ✅ Close and reopen files in Claude Code
- ✅ LSP features now work — no restart needed