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 httpxuv 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 installwith no environment. uv expects a virtual environment. It does not change the system Python unless you tell it to with--system. Make one withuv 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.organd*.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.
Related
- Run untrusted Python code safely.
- Install apt packages for system libraries.
- A data analysis agent that installs what its code imports.
Start
Terminalnpx withruntime sandboxes run -- uvx pycowsay hello from uvA 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
- uv documentation: https://docs.astral.sh/uv/, https://docs.astral.sh/uv/pip/, https://docs.astral.sh/uv/pip/environments/, https://docs.astral.sh/uv/concepts/projects/sync/, https://docs.astral.sh/uv/guides/scripts/ and https://docs.astral.sh/uv/guides/tools/, read 26 October 2026.
Facts on this page were checked on 26 October 2026.