.venv, are fully supported. typemux-cc maintains a backend pool that routes LSP requests to the correct backend based on file location.
The Problem
With Claude Code’s official pyright plugin:- Monorepo has 3 projects:
project-a/,project-b/,project-c/ - Each project has its own
.venvwith different dependencies - Opening
project-a/main.py→ pyright usesproject-a/.venv - Opening
project-b/main.py→ pyright still usesproject-a/.venv - Type checking fails because
project-bimports aren’t available - Must restart Claude Code to switch to
project-b/.venv
Monorepo Structure Example
From the README:- Has independent dependencies (different package versions)
- Has its own
.venv/pyvenv.cfg - Gets its own backend process in the pool
Backend Pool Routing
Pool Architecture
typemux-cc maintains a pool of backend processes, one per.venv:
Routing Logic
When Claude Code sends an LSP request:1
Extract document URI
2
Look up cached venv for document
3
Get backend from pool
4
Forward request to correct backend
If backend exists in pool, forward the request. If not, spawn a new backend (see “Operation Sequence” below).
Operation Sequence
From the README:Detailed Flow
1
Session starts
typemux-cc searches for a fallback If found, pre-spawns a backend. Otherwise starts with empty pool.
.venv at startup:2
Open project-a/src/main.py
VIRTUAL_ENV=project-a/.venv, session=1 added to pool.3
Open project-b/src/main.py
Same process, but:
.venvsearch findsproject-b/.venv- Not in pool → spawn new backend
- Backend with
VIRTUAL_ENV=project-b/.venv, session=2 added to pool
4
Return to project-a/src/main.py
What Actually Happens
From the README:When Claude Code moves fromproject-a/main.pytoproject-b/main.py:When Claude Code returns to
- Proxy detects different
.venv(project-a/.venv → project-b/.venv)- Checks the backend pool —
project-b/.venvnot found- Spawns new backend with
VIRTUAL_ENV=project-b/.venv(session 2)- Session 1 (project-a) stays alive in the pool — no restart
- Restores open documents under project-b/ to session 2
- Clears diagnostics for documents outside project-b/
- All LSP requests for project-b files now use project-b dependencies
project-a/main.pylater, session 1 is still in the pool — zero restart overhead.
Document Restoration
When a new backend spawns, typemux-cc restores already-open documents:Selective restoration: Only documents belonging to
project-b/ are restored to the project-b/.venv backend. project-a/ documents are skipped.Pool Management
Maximum Backends
Default: 8 concurrent backendsLRU Eviction
When the pool is full and a new backend is needed:- Prefer backends with no pending requests (safe to evict)
- Among those, pick the least recently used (oldest
last_usedtimestamp) - If all have pending requests, fall back to global LRU
TTL-Based Eviction
Default: 1800 seconds (30 minutes) of inactivitySwitching Between Projects
Switching is instant and automatic:- Open
project-a/src/main.py→ routes to session 1 - Hover over
pd.DataFrame→ request forwarded to session 1 - Open
project-b/src/main.py→ routes to session 2 - Hover over
np.array→ request forwarded to session 2 - Return to
project-a/src/main.py→ routes to session 1 (still in pool)
Real Monorepo Example
Here’s a realistic monorepo structure:- Independent dependencies (e.g.,
apiuses FastAPI,workeruses Celery) - Own
.venvwith different package versions - Own backend in the pool (up to 5 concurrent in this example)
1
Open api/src/main.py
Backend spawned:
VIRTUAL_ENV=services/api/.venv (session 1)2
Open worker/src/tasks.py
Backend spawned:
VIRTUAL_ENV=services/worker/.venv (session 2)3
Open libs/common/src/utils.py
Backend spawned:
VIRTUAL_ENV=libs/common/.venv (session 3)4
Return to api/src/main.py
Routes to session 1 (no spawn, instant)
Configuration for Monorepos
Increase max_backends for large monorepos
If you have more than 8 projects:Disable TTL for active development
To keep all backends alive indefinitely:Enable detailed logging
Troubleshooting
Wrong dependencies being used
Symptoms:- Import errors for packages that exist in the project’s venv
- Type checking fails with “module not found”
- Wrong venv cached: Document opened before correct
.venvexisted - Shared venv: Multiple projects using the same
.venvpath
Pool eviction too aggressive
Symptoms:- Backends being evicted while still needed
- Frequent “Creating new backend” in logs
TYPEMUX_CC_MAX_BACKENDStoo lowTYPEMUX_CC_BACKEND_TTLtoo short
Memory usage high with many backends
Each backend process uses ~200-500MB. With 16 backends: ~3-8GB total. Solutions:-
Reduce max_backends:
-
Enable TTL to evict idle backends:
- Close unused projects in Claude Code to reduce active backends
Summary
Monorepo checklist
- ✅ Each project has its own
.venv/pyvenv.cfg - ✅ Configure
TYPEMUX_CC_MAX_BACKENDSfor project count - ✅ Open files from different projects freely
- ✅ typemux-cc automatically routes to correct backends
- ✅ No restarts, no manual switching