Skip to main content

Axe

Tests PyPI

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
[axe] bootstrapping mycli 0.1.0...
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.

Documentation

Browsable at soasme.github.io/axe, or right here in the repo:

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
uv-releases-url = "https://mirror.corp/uv"    # download uv from a mirror
python-build-standalone-releases-url = "https://mirror.corp/pbs"  # ...and CPython
expose = ["metadata"]         # extra `self` commands: python, python-path,
                              # cache, metadata — or "all"
self-command-group = true     # false: don't reserve `self` at 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

If your CLI needs self for itself, set self-command-group = false in [tool.axe] and the binary reserves nothing — self reaches your app like any other argument.

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

Lint and formatting are enforced by pre-commit (ruff check + format); install the hooks once with uvx pre-commit install. CI runs the same hooks plus both test suites on every pull request.

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.5.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.5.0-py3-none-any.whl (5.4 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: axe-0.5.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.5.0.tar.gz
Algorithm Hash digest
SHA256 58a8e8837736f11a44b57a3bac9e177741d7699041a0ad80179519fdac9eb702
MD5 750eecab2e7a7e902f28b0d290dd1787
BLAKE2b-256 9b4c8a281e184b6ecbadf11bfcb9b1f85d51c96ad06c220fc6a4f39adc7b3803

See more details on using hashes here.

Provenance

The following attestation bundles were made for axe-0.5.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.5.0-py3-none-any.whl.

File metadata

  • Download URL: axe-0.5.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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 72540bc7fdc5d07bc762529de6ac361085a1fddc08425950af365e0d492a8642
MD5 134dc9ad6c2b63e57d8755289fa5c804
BLAKE2b-256 4fa850d214a6172ef72850065aa6a3d6b9f0c88deffa403416cd74c68bbef33f

See more details on using hashes here.

Provenance

The following attestation bundles were made for axe-0.5.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

This release

0.5.0 This release

2 files

0.3.0

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