-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Feature Request: Automatic UV Project Isolation for Git Worktrees
Problem Statement
When running uv commands (e.g., uv sync, uv run, uv add) from within a git worktree, uv's default project discovery mechanism searches upward through parent directories to find pyproject.toml. This causes worktrees to discover and use the parent repository's configuration instead of their own.
Example scenario:
# Main repo structure
/repo/
├─ .worktrees/
│ └─ issue-42-fix-auth/
│ └─ pyproject.toml (worktree-specific config)
└─ pyproject.toml (parent repo config)
# User navigates to worktree
cd /repo/.worktrees/issue-42-fix-auth
# Runs uv sync - expects to use worktree's pyproject.toml
uv sync
# BUT: uv discovers /repo/pyproject.toml instead
# Result: wrong dependencies installed, wrong scripts executedRoot Cause
UV's project discovery uses path.ancestors() to traverse upward until finding a pyproject.toml. In worktree scenarios (.worktrees/<branch-name>), it always finds the root repository's pyproject.toml first.
Source: uv/workspace.rs
Impact
- Incorrect dependency installation: Worktree installs packages for parent project instead of its own
- Wrong script execution:
uv runexecutes scripts from wrong project context - Environment pollution: Changes to dependencies in worktree affect parent repo and other worktrees sharing same
.venv - Impossible debugging: "Works on my machine" - last writer wins, non-deterministic behavior
- Test flakiness: Tests pass in one worktree, fail in another due to environment state changes
Proposed Solution
Implement automatic uv project isolation in ghwt using .envrc files (direnv integration) as primary mechanism with fallback wrapper script.
Implementation Details
1. Create .envrc file in each worktree:
# .worktrees/issue-42-fix-auth/.envrc
# Auto-generated by ghwt for uv project isolation
export UV_PROJECT="/absolute/path/to/repo/.worktrees/issue-42-fix-auth"
export UV_PROJECT_ENVIRONMENT="/absolute/path/to/repo/.worktrees/issue-42-fix-auth/.venv"How it works:
- Users install direnv (one-time setup)
- When entering a worktree via
cd, direnv automatically loads.envrc UV_PROJECTenvironment variable forces uv to use worktree'spyproject.toml- No manual intervention required - completely automatic
2. Create fallback wrapper script for non-direnv users:
#!/usr/bin/env bash
# scripts/uv-isolated.sh
export UV_PROJECT="$(pwd)"
export UV_PROJECT_ENVIRONMENT="$(pwd)/.venv"
uv "$@"Usage without direnv:
cd repo/.worktrees/issue-42-fix-auth
./scripts/uv-isolated.sh sync # Forces isolation3. Update .gitignore to prevent committing isolation files:
# UV isolation files in worktrees
.worktrees/*/.envrc
.worktrees/*/uv-isolated.sh
.worktrees/*/.env.local
Benefits
✅ Automatic isolation: No manual --project flag required by user
✅ Persistent: Configuration survives across sessions
✅ Shell-agnostic: Works with bash, zsh, fish, etc.
✅ Reversible: Users can direnv deny if needed
✅ Widely adopted: Standard tooling in modern dev environments
✅ Fallback available: Wrapper script for users without direnv
✅ Zero breakage: Doesn't affect users who don't use uv
Verification Commands
Users can verify uv is using correct project context:
cd repo/.worktrees/issue-42-fix-auth
uv project info
# Expected output:
# Project: /home/user/repo/.worktrees/issue-42-fix-auth
# Lockfile: /home/user/repo/.worktrees/issue-42-fix-auth/uv.lockEdge Cases Handled
| Edge Case | Handling Strategy |
|---|---|
Existing .envrc in worktree |
Append to existing file with marker # GHWT-UV-ISOLATION |
User manually runs uv --project /other/path |
Explicit --project flag takes precedence over UV_PROJECT env var (correct behavior) |
User sets UV_PROJECT globally |
.envrc overrides global setting due to export UV_PROJECT= syntax |
| Multiple worktrees open simultaneously | Each has its own .envrc, direnv loads/unloads on cd |
| User runs uv from subdirectory of worktree | UV_PROJECT points to worktree root, so uv finds worktree's pyproject.toml (correct) |
Implementation Plan
- Add
_create_envrc_file()method toWorktreeCreatorclass - Add
_create_uv_wrapper_script()method toWorktreeCreatorclass - Update worktree creation flow to call these methods
- Add unit tests for isolation file creation
- Add integration tests for full worktree creation with isolation
- Update README.md with UV isolation section
- Update WT_TASK_TEMPLATE.md with uv usage instructions
- Update
.gitignoreto exclude isolation files
Documentation Requirements
Add to README.md:
- Installation instructions for direnv
- How automatic isolation works
- Fallback wrapper script usage
- Verification commands
- Troubleshooting for edge cases
Acceptance Criteria
-
.envrcfile created in each worktree with correctUV_PROJECTpath - Wrapper script
scripts/uv-isolated.shcreated and executable - Unit tests pass for file creation
- Integration tests pass for full workflow
- README.md updated with complete documentation
-
.gitignoreupdated to exclude isolation files - Manual testing confirms isolation works with direnv
- Manual testing confirms wrapper script works without direnv
Additional Notes
Why NOT share .venv:
Research confirms that sharing .venv across worktrees causes dependency conflicts, "last writer wins" behavior, and impossible-to-debug issues. Each worktree should have its own isolated virtual environment.
Related research:
- uv project discovery mechanism
- direnv documentation
- Andrea Grandi's worktree patterns
- uvlink alternative approach (not using this - prefer native direnv)