Fast, cross-platform Python application packager with uv and Go
Project description
UVBOX
Fast, simple and cross-platform Python application packaging
Package your Python apps as self-boostrapping executables for every platforms.
Features • Comparison • Quick Start • Configuration • How It Works • Advanced Usage • Examples
What is uvbox?
uvbox generates standalone executables that bootstrap an embedded uv installation to automatically setup and run your Python application in a fully isolated environment — for any platform, from any platform.
No Python required on the target system. The binary handles everything: downloads the right Python version, creates a virtual environment, installs dependencies, and runs your app.
Features
- 📦 Package from PyPI or Wheels — Install your application from package indexes or choose to bundle local wheel files
- 🚀 True Cross-Compilation — Build binaries for Linux, macOS, and Windows (AMD64/ARM64) from any platform in seconds
- 🔄 Auto-Updates — Built-in version checking and self-update/fallback capabilities for your binaries
- 🔒 Dependency Freezing — Use constraints files to ensure reproducible installations
- 🌍 Enterprise-Friendly — Support for custom registries, mirrors, and CA certificates
- ⚡ Fast — Powered by Go, builds complete in very few seconds
- 📝 Simple Integration — Add as a dev dependency to your Python project
Comparison
| Feature | uvbox | pyapp | PyInstaller |
|---|---|---|---|
| Build Time | ~1s | ~30s | ~1-5min |
| Cross-Compilation | ✅ All platforms from any platform | ⚠️ Requires target toolchains | ❌ Native only |
| macOS from Linux/Windows | ✅ Out of the box | ❌ Forbidden by Apple license | ❌ Forbidden by Apple license |
| Updates | ✅ Built-in | ✅ Built-in | ❌ Manual |
| Fallbacks | ✅ Version fallback support | ❌ Not supported | ❌ Not supported |
| Distribution | Downloads at first run | Downloads at first run | Bundles everything (offline-ready) |
🎯 Choosing the right tool:
uvbox excels at fast, cross-platform builds with minimal setup, built-in automatic updates, and version fallback mechanisms. It downloads dependencies at first run, making binaries small but requiring internet connectivity initially.
PyInstaller bundles everything into the binary, creating larger files but ensuring complete offline functionality and maximum stability (no runtime network dependencies). However, it requires native builds per platform and lacks built-in update mechanisms.
💡 Use uvbox when: You want fast builds, easy cross-compilation, or when enforced updates/fallbacks may be required, and don't mind first-run downloads.
💡 Use PyInstaller when: You need guaranteed offline functionality, distribute in air-gapped environments, or only target a single platform (especially Linux-only deployments).
Quick Start
Installation
Add uvbox to your project from PyPI:
# With uv
uv add --dev uvbox
# With pip
pip install uvbox
[!NOTE] Installing from PyPI automatically includes Go and nfpm as dependencies, so you don't need to install them separately.
Basic Usage
Create a simple configuration and build:
# Create a minimal config file
cat > uvbox.toml <<EOF
[package]
name = "cowsay"
script = "cowsay"
EOF
# Build for all platforms
uvbox pypi --config uvbox.toml
# Output:
# ✓ DARWIN/AMD64 → cowsay-x86_64-apple-darwin.tar.gz
# ✓ DARWIN/ARM64 → cowsay-aarch64-apple-darwin.tar.gz
# ✓ LINUX/AMD64 → cowsay-x86_64-unknown-linux-gnu.tar.gz
# ✓ LINUX/ARM64 → cowsay-aarch64-unknown-linux-gnu.tar.gz
# ✓ WINDOWS/AMD64 → cowsay-x86_64-pc-windows-msvc.zip
Your executables are now in the dist/ directory!
Build from Wheels
Package local wheel files instead of installing from PyPI:
uvbox wheel --config uvbox.toml ./my-app.whl
Configuration
Using pyproject.toml
Embed configuration directly in your Python project:
[tool.uvbox.package]
name = "my-awesome-app"
script = "main" # Entry point from your package
[tool.uvbox.package.version]
dynamic = "https://example.com/my-app/version.txt" # Fetch version from URL
static = "1.0.0" # Fallback version if dynamic fetch fails
auto-update = true
# Optional: Constrain dependencies
[tool.uvbox.package.constraints]
dynamic = "https://example.com/my-app/<VERSION>/constraints.txt"
# uv index and mirror configuration will be automatically be used
[[tool.uv.index]]
name = "company-pypi"
url = "https://my.artifactory.com/artifactory/api/pypi/pypi-mirror/simple"
default = true
[tool.uv]
python-install-mirror = "https://my.github.remote/astral-sh/python-build-standalone/releases/download"
Then build directly from your project directory:
# uvbox automatically detects pyproject.toml
uvbox pypi
Using Standalone Config Files
Create a dedicated uvbox.toml file:
[package]
name = "my-app"
script = "my_entrypoint"
[package.version]
# Pin to specific version
static = "2.1.0"
# Or use dynamic version from URL
dynamic = "https://example.com/my-app/version.txt"
# Enable automatic updates before each run
auto-update = true
[package.constraints]
# Freeze dependencies with a constraints file
# <VERSION> placeholder is automatically replaced
dynamic = "https://example.com/my-app/<VERSION>/constraints.txt"
# Or use a static constraints file
static = "./constraints.txt"
[certificates]
# Bundle custom CA certificates (useful behind corporate firewalls)
path = "./ca-bundle.crt"
[uv]
# Optional: Specify which uv version to use
version = "0.4.20"
# Optional: Use a mirror for downloading uv itself
mirror = "https://mirror.example.com/uv/releases/download"
# Configure uv runtime behavior with environment variables
environment = [
"UV_INDEX_URL=https://pypi.example.com/simple",
"UV_PYTHON=3.12",
"UV_PYTHON_INSTALL_MIRROR=https://mirror.example.com/python-builds"
]
Configuration Reference
[package]
Core package configuration.
name(required) — Package name to install from PyPIscript(required) — Entry point script to run (from[project.scripts]in your package)
[package.version]
Version management and updates.
static— Pin to a specific version (e.g.,"1.2.3")dynamic— URL to a text file containing the version to installauto-update— Check for updates before each run (may slow startup)
[package.constraints]
Dependency freezing for reproducible installs.
static— Path to local constraints filedynamic— URL to remote constraints file (supports<VERSION>placeholder)
[certificates]
Bundle custom CA certificates.
path— Path to certificate bundle (relative to working directory)
The binary automatically sets REQUESTS_CA_BUNDLE and SSL_CERT_FILE environment variables.
[uv]
Configure uv installation and behavior.
version— Specific uv version to download and use (e.g.,"0.4.20")mirror— Alternative download URL for uv releases (e.g.,"https://mirror.example.com/uv/releases/download")environment— Array of environment variables to set for uv runtime behavior
See uv's documentation for available environment variables.
Config File Discovery
uvbox automatically searches for configuration files:
- Explicit path via
--configflag uvbox.tomlin current directory or parentspyproject.tomlwith[tool.uvbox]section in current directory or parents
How It Works
uvbox leverages Go's powerful cross-compilation to create lightweight executables that:
- Embed uv — Each binary contains the uv installation URL and configuration
- Bootstrap on First Run — Downloads and extracts uv to an isolated XDG-compliant directory
- Install Your App — Uses
uv tool installto set up your package and dependencies in complete isolation - Run — Executes your application's entry point with the configured environment
All files are stored in XDG-compliant directories ($XDG_DATA_HOME/uvbox/ or ~/.local/share/uvbox/ by default), ensuring a clean and standardized file system layout.
Why Go?
- ⚡ Blazing Fast Compilation — ~1 second vs ~30 seconds for Rust-based alternatives
- 🌍 True Cross-Compilation — Build macOS binaries from Linux/Windows without licenses or complex toolchains
- 📦 Zero Dependencies — Just set
GOOSandGOARCHenvironment variables - 🎯 Simple Deployment — Single static binary, no runtime dependencies
Runtime Behavior
When a user runs your binary:
./my-app --help
The first run automatically:
- Extracts embedded uv to
$XDG_DATA_HOME/uvbox/<identifier>/uv/(defaults to~/.local/share/uvbox/<identifier>/uv/) - Downloads Python if needed to
$XDG_DATA_HOME/uvbox/<identifier>/python/(defaults to~/.local/share/uvbox/<identifier>/python/) - Installs your package in an isolated environment at
$XDG_DATA_HOME/uvbox/<identifier>/tools/(defaults to~/.local/share/uvbox/<identifier>/tools/) - Runs your script
Subsequent runs skip straight to execution (unless updates are configured).
[!NOTE] The
<identifier>is a hash computed from your package name, script, and configuration to ensure complete isolation between different applications.
Built-in Commands
Every generated binary includes these self commands:
<app> self update— Update the package to the latest available version<app> self remove— Remove installation (clean up installed files and virtual environment)<app> self path— Display paths related to the installation<app> self cache— Manage cache<app> self uv— Run installation uv executable inside the isolated environment
Advanced Usage
Linux Package Generation
Generate .deb and .rpm packages alongside binaries:
# Create nfpm.yaml configuration
cat > nfpm.yaml <<EOF
name: my-app
maintainer: "Your Name <you@example.com>"
description: "My awesome application"
homepage: "https://github.com/you/my-app"
license: "MIT"
# Template variables
arch: ${UVBOX_ARCH}
platform: ${UVBOX_PLATFORM}
version: ${UVBOX_VERSION}
# Copy executable to target folder
contents:
- src: ${UVBOX_BUILT_EXECUTABLE}
dst: /usr/bin/my-app
# Built-in pre-remove script that ensures application data are removed
scripts:
preremove: ./pre_remove.sh
EOF
# Build with packaging
uvbox pypi --nfpm nfpm.yaml --release-version 1.0.0
Available Template Variables:
uvbox provides environment variables for use in your nfpm configuration:
UVBOX_BUILT_EXECUTABLE— Absolute path to the compiled executableUVBOX_NAME— Executable name (fromscriptconfiguration)UVBOX_PLATFORM— Target platform (linux,darwin,windows)UVBOX_ARCH— Target architecture (amd64,arm64)UVBOX_VERSION— Version from--release-versionflag
Use them with ${VARIABLE_NAME} syntax in your nfpm.yaml.
[!TIP] The
preremove: ./pre_remove.shscript is optional. If you include it in your nfpm configuration, uvbox automatically generates it to call<executable> self remove, which cleans up application data (virtual environments, cached Python installations) when the package is uninstalled.
Custom Registry Example
[package]
name = "internal-tool"
script = "tool"
[uv]
environment = [
"UV_INDEX_URL=https://artifactory.company.com/api/pypi/pypi-mirror/simple",
"UV_EXTRA_INDEX_URL=https://artifactory.company.com/api/pypi/internal-packages/simple",
"UV_PYTHON_INSTALL_MIRROR=https://internal-mirror.company.com/python-builds"
]
[certificates]
path = "./company-ca-bundle.crt"
Version Fallback Strategy
Use dynamic versioning with fallback:
[package.version]
# Try to fetch latest version from URL
dynamic = "https://cdn.example.com/my-app/latest.txt"
# Fallback to this version if URL is unreachable
static = "1.0.0"
# Check for updates before each run
auto-update = true
Examples
See the examples/ directory for complete working examples:
examples/pypi/simple-app.toml— Minimal PyPI packageexamples/pypi/custom-registry.toml— Custom registry and mirrorsexamples/pypi/custom-certs.toml— Corporate CA bundle
Requirements
Build Time
- Go 1.21+ (automatically fetched if installed via PyPI package)
- nfpm (optional, only if generating
.deb/.rpmpackages)
Runtime (Generated Binaries)
- libc (standard C library, required by Python itself)
License
MIT © 2025 Amadeus
Contributing
We welcome contributions!
Acknowledgments
Heavily inspired by the excellent pyapp project. Built with:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file uvbox-1.0.4-py3-none-win_arm64.whl.
File metadata
- Download URL: uvbox-1.0.4-py3-none-win_arm64.whl
- Upload date:
- Size: 3.7 MB
- Tags: Python 3, Windows ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79923643244dbe036b5756ac6ce83bace4748b85d85e095630bcd97335263b1d
|
|
| MD5 |
70eb387d4856572b11d42090a8b47654
|
|
| BLAKE2b-256 |
fe2a9906ff35ab079f4d21843a2519e91333f4c8a4d799b066665690aa5e6603
|
Provenance
The following attestation bundles were made for uvbox-1.0.4-py3-none-win_arm64.whl:
Publisher:
release.yml on AmadeusITGroup/uvbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvbox-1.0.4-py3-none-win_arm64.whl -
Subject digest:
79923643244dbe036b5756ac6ce83bace4748b85d85e095630bcd97335263b1d - Sigstore transparency entry: 773460133
- Sigstore integration time:
-
Permalink:
AmadeusITGroup/uvbox@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AmadeusITGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file uvbox-1.0.4-py3-none-win_amd64.whl.
File metadata
- Download URL: uvbox-1.0.4-py3-none-win_amd64.whl
- Upload date:
- Size: 4.1 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecb8a8d7d7eeef278ec840911b7983b6d08d080c8d2fa6d7531c49a9ab765589
|
|
| MD5 |
348d146c1250070ef6db8cff46f504e1
|
|
| BLAKE2b-256 |
a283839f86d1f9a354a1be3f1965f23fd4bbacd6e5c6f1383ecaf4abf1a8a31e
|
Provenance
The following attestation bundles were made for uvbox-1.0.4-py3-none-win_amd64.whl:
Publisher:
release.yml on AmadeusITGroup/uvbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvbox-1.0.4-py3-none-win_amd64.whl -
Subject digest:
ecb8a8d7d7eeef278ec840911b7983b6d08d080c8d2fa6d7531c49a9ab765589 - Sigstore transparency entry: 773460072
- Sigstore integration time:
-
Permalink:
AmadeusITGroup/uvbox@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AmadeusITGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file uvbox-1.0.4-py3-none-manylinux2014_x86_64.whl.
File metadata
- Download URL: uvbox-1.0.4-py3-none-manylinux2014_x86_64.whl
- Upload date:
- Size: 4.0 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2f12086533426fd4caecb26a9e2649dd1d09d124ee10ca8c1952305f0d3ef4ac
|
|
| MD5 |
f99a94e3bb73c13791962ddc171a8f35
|
|
| BLAKE2b-256 |
7c58ca5b63ab455d0eeaa315f32d2652aa636ac9da9386529383ead41265f547
|
Provenance
The following attestation bundles were made for uvbox-1.0.4-py3-none-manylinux2014_x86_64.whl:
Publisher:
release.yml on AmadeusITGroup/uvbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvbox-1.0.4-py3-none-manylinux2014_x86_64.whl -
Subject digest:
2f12086533426fd4caecb26a9e2649dd1d09d124ee10ca8c1952305f0d3ef4ac - Sigstore transparency entry: 773460099
- Sigstore integration time:
-
Permalink:
AmadeusITGroup/uvbox@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AmadeusITGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file uvbox-1.0.4-py3-none-manylinux2014_aarch64.whl.
File metadata
- Download URL: uvbox-1.0.4-py3-none-manylinux2014_aarch64.whl
- Upload date:
- Size: 3.7 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a17f16ff480387f227c6e2764b1ba36d9adf579a1b4dc9616fa1b33093ab2f15
|
|
| MD5 |
8693c1f1b2d24bb70a9805c6ae7b28ab
|
|
| BLAKE2b-256 |
862b3dfce293d666182e183d18d60ff2d87e8229dc7ac88eef98d8e09c42aee2
|
Provenance
The following attestation bundles were made for uvbox-1.0.4-py3-none-manylinux2014_aarch64.whl:
Publisher:
release.yml on AmadeusITGroup/uvbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvbox-1.0.4-py3-none-manylinux2014_aarch64.whl -
Subject digest:
a17f16ff480387f227c6e2764b1ba36d9adf579a1b4dc9616fa1b33093ab2f15 - Sigstore transparency entry: 773460153
- Sigstore integration time:
-
Permalink:
AmadeusITGroup/uvbox@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AmadeusITGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file uvbox-1.0.4-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: uvbox-1.0.4-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.8 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
503167d24d5174771dec7f934e33e8b9f528e63e126bf20013a8d7793014fc92
|
|
| MD5 |
67663870893fd95899c845d04db3df1f
|
|
| BLAKE2b-256 |
a2604ea085bbe4a9e724e492476ec9365a8d00140e0368084c1eb916ed5279ca
|
Provenance
The following attestation bundles were made for uvbox-1.0.4-py3-none-macosx_11_0_arm64.whl:
Publisher:
release.yml on AmadeusITGroup/uvbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvbox-1.0.4-py3-none-macosx_11_0_arm64.whl -
Subject digest:
503167d24d5174771dec7f934e33e8b9f528e63e126bf20013a8d7793014fc92 - Sigstore transparency entry: 773460084
- Sigstore integration time:
-
Permalink:
AmadeusITGroup/uvbox@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AmadeusITGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file uvbox-1.0.4-py3-none-macosx_10_9_x86_64.whl.
File metadata
- Download URL: uvbox-1.0.4-py3-none-macosx_10_9_x86_64.whl
- Upload date:
- Size: 4.0 MB
- Tags: Python 3, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7de05e6636f0f85ff606cb4fe77185259b0bbb3ec3587a315d025d89ca186a96
|
|
| MD5 |
11d11c9284cc0264ec163206e0e96a65
|
|
| BLAKE2b-256 |
a2a4178233ed7def3032fb7c93a28f7f75266414e00ca7fe2292326ec5fc08ae
|
Provenance
The following attestation bundles were made for uvbox-1.0.4-py3-none-macosx_10_9_x86_64.whl:
Publisher:
release.yml on AmadeusITGroup/uvbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
uvbox-1.0.4-py3-none-macosx_10_9_x86_64.whl -
Subject digest:
7de05e6636f0f85ff606cb4fe77185259b0bbb3ec3587a315d025d89ca186a96 - Sigstore transparency entry: 773460112
- Sigstore integration time:
-
Permalink:
AmadeusITGroup/uvbox@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/AmadeusITGroup
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@100b23e9bc9a0b2247850d4eb66161b011e9f399 -
Trigger Event:
workflow_dispatch
-
Statement type: