Skip to content
Runtime

How to install Python packages with uv in a sandbox

uv is preinstalled: run uv venv, then uv pip install <package>, or uv sync in a project that has a uv.lock.

On Runtime, uv is part of the default image, so you do not need to install it first. Every sandbox has uv 0.12.17 (uv and uvx) alongside Python 3.12 and pip (what is installed). Each sandbox is a Firecracker microVM of its own, so a package's install script runs away from your machine. uv's own documentation calls it "10-100x faster than pip". It also describes uv as a drop-in replacement for common pip commands.

Install into a virtual environment

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create();const slow = { check: true, timeoutMs: 300_000 } as const;await sbx.exec("uv venv /workspace/.venv", slow);await sbx.exec("uv pip install polars httpx", { ...slow, cwd: "/workspace" });const run = await sbx.exec([".venv/bin/python", "-c", "import polars; print(polars.__version__)"]);console.log(run.stdout);
Pythonfrom withruntime import Sandboxwith Sandbox.create() as sbx:    sbx.exec("uv venv /workspace/.venv", check=True, timeout_ms=300_000)    sbx.exec("uv pip install polars httpx", cwd="/workspace", check=True, timeout_ms=300_000)    run = sbx.exec([".venv/bin/python", "-c", "import polars; print(polars.__version__)"])    print(run.stdout)
Terminalruntime sandboxes exec "${id}" -- uv venv /workspace/.venvruntime sandboxes exec "${id}" --cwd /workspace --timeout 300 -- uv pip install polars httpx

uv pip install finds .venv in the working directory. That is why the second command runs in /workspace. It uses a virtual environment and does not write into the system Python.

Install a project from its lockfile

A project with pyproject.toml and uv.lock installs exactly the versions it locked. Upload the project, sync it, and run it:

TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ timeoutSeconds: 1800 });await sbx.files.upload("./service", "/workspace/service");const inProject = { cwd: "/workspace/service", check: true, timeoutMs: 600_000 } as const;await sbx.exec("uv sync --frozen", inProject);const tests = await sbx.exec("uv run pytest -q", { ...inProject, check: false });console.log(tests.exitCode, tests.stdout);
Pythonfrom withruntime import Sandboxwith Sandbox.create(timeout_seconds=1800) as sbx:    sbx.files.upload("./service", "/workspace/service")    sbx.exec("uv sync --frozen", cwd="/workspace/service", check=True, timeout_ms=600_000)    tests = sbx.exec("uv run pytest -q", cwd="/workspace/service", timeout_ms=600_000)    print(tests.exit_code, tests.stdout)

--frozen uses the lockfile as it is. It does not check whether the lockfile is up to date, so the sandbox runs what your laptop and CI ran. For a one-off tool, uvx ruff check . runs it in a throwaway environment. To add a package for one run, use uv run --with requests script.py.

Start every sandbox with the environment ready

Build the environment into a custom image. Recipe commands run as root. So put the environment outside /workspace, and call its Python by path:

TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({  name: "uv-data",  recipe: {    commands: ["uv venv /opt/venv", "uv pip install --python /opt/venv/bin/python polars duckdb"],  },});await using sbx = await runtime.sandboxes.create({ image: "uv-data" });await sbx.exec(["/opt/venv/bin/python", "-c", "import duckdb, polars"], { check: true });

Building is free. A stored image costs $0.08 per decimal GB per 30-day month. An account without credit stores its first three images free (pricing). When plain pip is enough, a recipe's pip list is the shorter path.

uv or pip?

Task uv pip in the sandbox
Quick install for one job uv venv then uv pip install ... pip install ..., no environment needed
Exact versions from a lockfile uv sync --frozen pip install -r requirements.txt (pinned)
Run a CLI tool once uvx <tool> pip install then run it
Another Python version uv run --python 3.13 ... downloads it Not with pip
Where packages go The virtual environment you made /workspace/.local as the user, /usr/local under sudo

Plain pip install works here without a virtual environment. The image's /etc/pip.conf sets break-system-packages, so Ubuntu's PEP 668 guard does not stop it (who you are).

Mistakes and how Runtime handles them

  • uv pip install with no environment. uv expects a virtual environment. It does not change the system Python unless you tell it to with --system. Make one with uv venv, or use pip for a system-wide install.
  • A command that times out. A large install can run past the 60-second default for a command. Set timeoutMs. A timeout returns the output so far.
  • An allow list without the package index. With narrowed network rules, allow pypi.org and *.pythonhosted.org. Or install before you turn the internet off (turn off sandbox internet).
  • Keeping the key to a private index. Store it as a secret the sandbox never sees. The proxy adds it to HTTPS requests to the index's host only.
  • Disk. Wheels for large libraries fill a small disk. The default 4 GiB sandbox had about 2.5 GiB free on 24 September 2026. Ask for more with diskMiB.

Start

Terminalnpx withruntime sandboxes run -- uvx pycowsay hello from uv

A new account gets 100 free hours of a 1 GB machine in its first 30 days, with no card needed. The first run prints a link to approve in your browser.

Sources

Facts on this page were checked on 26 October 2026.

100 free hoursin your first 30 days.

of a 1 GB machine

  • No credit card
  • Four sandboxes at once, 2 vCPU and 4 GiB each
  • Then prepaid credit from $10, no plan fee
Start free, no card
Start free, no card