Skip to main content

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 build glues 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.

The full runtime flow — and how it maps onto pyapp's — is documented in docs/runtime.md. Apps run in Python's isolated mode, so the user's PYTHONPATH, user site-packages, and uv/pip configuration never leak in.

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

Runtime behavior is documented in docs/runtime.md.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

axe-0.3.0.tar.gz (5.4 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

axe-0.3.0-py3-none-any.whl (5.4 MB view details)

Uploaded Python 3

File details

Details for the file axe-0.3.0.tar.gz.

File metadata

  • Download URL: axe-0.3.0.tar.gz
  • Upload date:
  • Size: 5.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for axe-0.3.0.tar.gz
Algorithm Hash digest
SHA256 e939282ec6becb18a79cb2cb4c2ab2fe739c13549288b40fbe81c77e3c0fbf92
MD5 d2d83397545a5621ebddf955f011f068
BLAKE2b-256 25633e2ff191ffe2a2ba088f8a3f7d95436ad9d0b2a3045877a48b752eb127a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for axe-0.3.0.tar.gz:

Publisher: publish.yml on soasme/axe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file axe-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: axe-0.3.0-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

Hashes for axe-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 71091070a2628ada2a4a6670e4227cabc465f2991f7ec03436c08719f68838d4
MD5 0f6233fca48efb3ccadc3204ff409432
BLAKE2b-256 9408d0e759500e003eb90329dbbf9178caca7798f58004dc23c89edbadccdd1f

See more details on using hashes here.

Provenance

The following attestation bundles were made for axe-0.3.0-py3-none-any.whl:

Publisher: publish.yml on soasme/axe

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.5.1

2 files

0.5.0

2 files

This release

0.3.0 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

0.0.4

1 file

0.0.3

1 file

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page