uv-devcontainer is a small Bash-based uv shim that transparently runs uv run inside a project's Dev Container while leaving Codex, Claude, editors, and other host tools on the host.
When no supported Dev Container configuration exists, project-oriented uv commands run on the host with UV_PROJECT_ENVIRONMENT pointing outside the repository. This avoids creating project-local .venv directories.
- Bash 3.2 or newer.
- A real
uvexecutable on the host. - Standard Unix utilities:
awk,find,sort, and one ofshasum,sha256sum, oropenssl. - For Dev Container projects: Docker, the Dev Container CLI (
devcontainer), anduvinside the container.
On macOS with Homebrew:
brew install uv devcontainer
brew install --cask dockerDocker Desktop is needed only if no compatible container engine is already available.
Install the runtime shim and add it to the current shell's startup file:
./install.shAlso inject the runtime instructions into both Codex and Claude user instruction files:
./install.sh --agentsInject instructions for only one agent:
./install.sh --codex
./install.sh --claudeThe default installation prefix is ${XDG_DATA_HOME:-$HOME/.local/share}/uv-devcontainer. The installer adds <prefix>/bin to PATH using a managed block in ~/.zshenv, ~/.bashrc, or ~/.profile, depending on the current shell.
Start a new shell after installation, or activate it immediately:
export PATH="${XDG_DATA_HOME:-$HOME/.local/share}/uv-devcontainer/bin:$PATH"Useful options:
--prefix PATH Use a custom installation prefix.
--shell-file PATH Inject PATH into a specific shell startup file.
--no-shell Do not modify a shell startup file.
--codex-file PATH Use a specific Codex instruction file.
--claude-file PATH Use a specific Claude instruction file.
--agents Inject both Codex and Claude instructions.
The installer is idempotent. Existing files are preserved, managed blocks are replaced in place, and the first version of every edited file is retained beside it with a .uvdc-backup suffix.
The wrapper finds the nearest parent directory containing pyproject.toml or uv.toml and treats it as the Python project root.
For uv run:
- Look for
.devcontainer/devcontainer.json,.devcontainer.json,.devcontainer/base/devcontainer.json, or exactly one.devcontainer/*/devcontainer.jsonunder the project root. - Reuse a running Dev Container when possible, otherwise start it with
devcontainer up. - Preserve the caller's project-relative working directory.
- Run
uv run --activeinside the container. - Refuse to fall back to the host if the Dev Container exists but cannot start.
When no Dev Container configuration exists, uv run, uv sync, uv add, uv remove, uv tree, uv lock, and uv export use an environment under ${UVDC_ENV_BASE:-${TMPDIR:-/tmp}/uv-project-envs}.
Use the explicit escape hatch when host execution is required:
uv-host run ...The equivalent environment override is:
UVDC_HOST=1 uv run ...Inside a container, UVDC_IN_DEVCONTAINER=1 prevents recursive dispatch. The wrapper also bypasses dispatch when /.dockerenv exists.
Discovery starts at the nearest Python project root, not necessarily the Git repository root. In a monorepo, place the Dev Container configuration at that Python root or add a uv.toml at the intended workspace root.
./doctor.sh
./install.sh --statusdoctor.sh checks runtime dependencies, installation state, PATH ordering, and agent instruction injection. Docker and the Dev Container CLI are reported as optional until a Dev Container project is used.
The installer refuses to install the wrapper when it cannot find a separate, real uv executable. On macOS it recommends:
brew install uvA missing Dev Container CLI or Docker installation does not prevent host-only Python projects from working. The installer and doctor report the missing optional capability and recommend:
brew install devcontainer
brew install --cask dockerIf a project has a Dev Container configuration but devcontainer is unavailable, uv run stops with the installation recommendation instead of falling back to the host.
After the container starts, the dispatcher verifies that uv is available inside it. If it is missing, execution stops with guidance to add uv to the container image, Dev Container features, or lifecycle configuration. A host-side brew install uv cannot supply tools inside the container.
./uninstall.shUninstall removes only the known installed runtime files and managed configuration blocks. It does not remove backups or unrelated files in the installation prefix.
If a custom prefix or configuration path was used, pass the same options during uninstall:
./uninstall.sh --prefix /custom/prefix --shell-file ~/.custom-shellThe smoke suite uses isolated fake uv and devcontainer executables; it does not start Docker or modify user configuration:
./tests/smoke.sh