Zero-friction Python app compiler: ship any Python project as a self-bootstrapping single-file binary.
Project description
Axe
Axe ships your Python app as a fully self-contained single-file binary — for every major platform, from any machine, with zero extra toolchain.
- App developers need no Go, no cross-compilers, no Docker. Axe's wheel
ships precompiled runtime stubs;
axe buildglues your app onto them. - App users need no Python, no uv, and no network. The binary embeds uv, CPython, and every dependency wheel; the first run unpacks them into a cached environment and every run after is instant. Corporate proxy, air-gap, TLS-intercepting middlebox — none of it matters.
Quick start
Your project needs to be an installable package with a console script — a
project created with uv init --package is already set up correctly (a bare
uv init app is not packaged; axe build will tell you what to add):
$ uv init --package mycli
$ cd mycli
$ uv add --dev axe
$ uv run axe build --all-platforms
built dist/bin/mycli-0.1.0-linux-amd64 (52 MB, python 3.12.13, 0 dependency wheels)
built dist/bin/mycli-0.1.0-linux-arm64 (50 MB, python 3.12.13, 0 dependency wheels)
built dist/bin/mycli-0.1.0-darwin-amd64 (48 MB, python 3.12.13, 0 dependency wheels)
built dist/bin/mycli-0.1.0-darwin-arm64 (47 MB, python 3.12.13, 0 dependency wheels)
built dist/bin/mycli-0.1.0-windows-amd64.exe (55 MB, python 3.12.13, 0 dependency wheels)
Hand the binary to anyone — nothing to install, nothing to download:
$ ./dist/bin/mycli-0.1.0-darwin-arm64
setting up mycli 0.1.0 (first run)...
done.
Hello from mycli!
$ ./dist/bin/mycli-0.1.0-darwin-arm64 # instant from now on
Hello from mycli!
A fuller example lives in examples/cowsay.
How it works
axe build assembles, per target platform, a payload containing everything a
machine needs to run your app:
- your project's wheel (built with uv),
- every dependency wheel, resolved for that platform (
uv pip compile --python-platform+pip download), - a pinned CPython from python-build-standalone,
- a pinned uv,
and appends it to a small precompiled Go runtime stub. All artifacts are fetched once on the build machine (checksum-verified, cached), so builds after the first are seconds.
At first run the stub unpacks the embedded Python and uv, creates a venv, and
installs the embedded wheels with --offline --no-index — the runtime
contains no network code at all. Installations live in a per-app directory
keyed by payload fingerprint, so a new binary version gets a fresh
environment automatically. Subsequent runs are a single existence check, then
execvp straight into your app.
Because dependencies are shipped as wheels, every dependency must publish a wheel for each target platform (pure-Python wheels cover all of them). Binaries weigh roughly 45–60 MB — that's a complete CPython plus uv; disk is cheap, broken installs are not.
Configuration
Everything is optional; defaults come from [project]:
[tool.axe]
entrypoint = "mycli" # default: the sole [project.scripts] entry
# also accepts "-m pkg" or "pkg.mod:func"
python = "3.12" # "3.X" picks the newest 3.X.*; "3.X.Y" pins
# default: lower bound of requires-python
uv-version = "0.10.6" # uv embedded into the binary
python-release = "20260623" # python-build-standalone release tag
expose = ["metadata"] # extra `self` commands: python, python-path,
# cache, metadata — or "all"
CLI
$ axe build [PROJECT] [-o DIR] [-p OS/ARCH]... [--all-platforms] [-q | -v]
$ axe platforms
-q/--quiet prints nothing but errors; -v/--verbose streams the output
of the underlying tools (useful behind corporate proxies — if downloads fail
or stall there, set UV_NATIVE_TLS=1 so uv uses the system trust store).
Targets: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64,
windows/amd64.
Runtime management commands
Built binaries reserve one command group, self; everything else goes to
your app:
$ myapp self remove # wipe the installation
$ myapp self restore # wipe and reinstall
$ myapp self update # reinstall from the embedded payload
AXE=1 is set in your app's environment so it can detect axe installs, and
AXE_DEBUG=1 makes the stub verbose.
Developing axe itself
This is the one place a Go toolchain is required:
$ python scripts/build_stubs.py # cross-compile runtime stubs (needs go)
$ uv run pytest # unit + end-to-end tests (offline-verified)
$ cd runtime && go test ./... # runtime unit tests
$ uv build # the wheel, stubs included
Design doc: docs/superpowers/specs/2026-07-07-axe-design.md.
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 Distribution
Built Distribution
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 axe-0.2.1.tar.gz.
File metadata
- Download URL: axe-0.2.1.tar.gz
- Upload date:
- Size: 5.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb711624f336cc0510e55f53f4357d39670537ba723d4270f93618c28f481ff8
|
|
| MD5 |
551cb1670710cc93e9502dcfdcea8ee8
|
|
| BLAKE2b-256 |
b107d769ab137942ea4fd82a2b030741c3eb546772a10fc2d17d39f5f0fbd4fe
|
Provenance
The following attestation bundles were made for axe-0.2.1.tar.gz:
Publisher:
publish.yml on soasme/axe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
axe-0.2.1.tar.gz -
Subject digest:
eb711624f336cc0510e55f53f4357d39670537ba723d4270f93618c28f481ff8 - Sigstore transparency entry: 2106869576
- Sigstore integration time:
-
Permalink:
soasme/axe@1942075c5ef2795758a60605abdf5a25d0699399 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/soasme
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1942075c5ef2795758a60605abdf5a25d0699399 -
Trigger Event:
push
-
Statement type:
File details
Details for the file axe-0.2.1-py3-none-any.whl.
File metadata
- Download URL: axe-0.2.1-py3-none-any.whl
- Upload date:
- Size: 5.4 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48483805935fa604180d77e491e5f33e4abf67c403fbff8d72979cb9a2ae7107
|
|
| MD5 |
b1f0c7d3da8f967601e1b609937828e7
|
|
| BLAKE2b-256 |
eb904ec6bcc2b7fa00d2f72616802a96b5c29551c8100c65f3c6f5b05f38484b
|
Provenance
The following attestation bundles were made for axe-0.2.1-py3-none-any.whl:
Publisher:
publish.yml on soasme/axe
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
axe-0.2.1-py3-none-any.whl -
Subject digest:
48483805935fa604180d77e491e5f33e4abf67c403fbff8d72979cb9a2ae7107 - Sigstore transparency entry: 2106869650
- Sigstore integration time:
-
Permalink:
soasme/axe@1942075c5ef2795758a60605abdf5a25d0699399 -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/soasme
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1942075c5ef2795758a60605abdf5a25d0699399 -
Trigger Event:
push
-
Statement type: