Python wrapper for the PyCrucible CLI tool
Project description
Sections
- What is PyCrucible?
- Quickstart
- Installation
- Usage
- Runtime Configuration
- Embedding Options
- Github Action
- Security
- How it works
- Features
- Community
- Changelog
- Thanks to
What is PyCrucible?
PyCrucible packages any Python project into a single cross-platform executable with minimal overhead, powered by Rust and uv.
Existing tools like PyInstaller bundle the entire Python interpreter, dependencies, and project files. This typically results in:
- large binaries
- slow builds
- dependency complexity
- fragile runtime environments
PyCrucible is diffrent
- Fast and robust — written in Rust
- Multi-platform — Windows, Linux, macOS
- Tiny executables — ~2MB + your project files (if using
--no-uv-embedflag [added: v0.4.0]) - Support for
*.whlembedding [added: v0.4.0] - Hassle-free dependency resolution — delegated to uv
- Simple but configurable
- Supports auto-updates (GitHub public repos)
- Includes a GitHub Action for CI automation
[!NOTE] On the first run, PyCrucible downloads project dependencies through uv.
Subsequent runs start instantly.
Quickstart
If you dont want to read the specifics, jump right in. Its easy to use:
pip install pycrucible
pycrucible -e . -o ./myapp
How to install PyCrucible
There are a couple of ways to install PyCrucible.
- using
PyPi - downloading from Github Releases
- compiling source code
Using PyPi
PyCrucible is published to PyPi for every release. All you need to do is:
pip install pycrucible
[!TIP] You can also use
pipx,uvoruvxto download and install PyCrucible fromPyPi.
[!NOTE] PyCrucible on
PyPiis compiled withglibc==2.28making sure its compatible with older operating systems.
Using Github Releases
You can download pre-made binaries for your system from
Downloading and building from source code
-
Ensure you have Rust installed.
-
Clone the repository
git clone https://github.com/razorblade23/PyCrucible
- Change directory to be inside of a project
cd PyCrucible
- Build Runner
cargo build -p pycrucible_runner --release
- Build Pycrucible
cargo build -p pycrucible --release
[!NOTE] The resulting binary will be in
target/release/pycrucible.
How to use PyCrucible
All you need for starting is a single main.py file with some code.
Documentation
Documentation can be found at PyCrucible docs.
Example project
This is our example project.
def main():
print("Hello from PyCrucible binary")
if __name__ == "__main__":
main()
[!IMPORTANT] PyCrucible defaults to
src/main.pyso that is how you should save your file, but you can override this with entrypoint configuration.
[!TIP] It would also be nice if you had
pyproject.tomlfile, but this is not a requirement. If you do use configuration file, setting entrypoint directive is required.Example
pyproject.toml[project] name = "pycrucible-example" version = "0.1.0" description = "Simple example in using PyCrucible" requires-python = ">=3.12" dependencies = [] [tool.pycrucible] entrypoint = "main.py"
Now that we have our ingredients, lets make a binary using PyCrucible.
$ pycrucible -e .
This will embed your project and produce a new binary which is by default called launcher (or launcher.exe on Windows).
[!TIP] To configure the output path and name of your binary, use
-oor--outputflag.Example:
pycrucible -e . -o ./myapp(orpycrucible -e . -o ./myapp.exe)
This is now all you need to distribute your python project to other people. No python required on their end. Just this single binary.
It does not have to be a .py script
In web apps it is common to run some server that will handle your requests. In PyCrucible, entrypoint, pre-run or post-run do not need to be .py scripts.
You can use anything from your dependacies as a starting point. For example, you could run your flask application like this:
# pyproject.toml
...
[tool.pycrucible]
entrypoint = "gunicorn --port 9000 --host '0.0.0.0' app.app"
Everything that you pass as entrypoint, pre-run or post-run will be used just like you would run those commands within your enviroment.
PyCrucible configuration
Configuration can be set in any of these files:
pycrucible.tomlpyproject.toml
[!IMPORTANT] When using any configuration option, only
entrypoint(orentry) is required. Other options are optional.
Supported configuration options are:
- entrypoint (entry) - The main file your application must run. Usually
main.pyorapp.py. - options
- debug - Enable debug output during runtime of binary. Used for debugging.
- extract_to_temp - Extract the project files to temporary directory instead of directory next to binary.
- delete_after_run - Delete source files after running.
- patterns
- include - What files to include into your final binary.
- exclude - What files to exclude from your final binary.
- env - key-value pairs of enviroment variables that will be set before running your binary.
- hooks
- pre-run - Run this script before running main application. Useful for pre-loading of data. Must be Python script.
- post-run - Run this script after running main application. Useful for unloading of data. Must be Python script.
[!NOTE] When both
pycrucible.tomlandpyproject.tomlare discovered, configuration frompycrucible.tomlwill take effect.
Both of these files have exact same configuration options
You can find example configuration file for pycrucible.toml here
Only diffrence between these files is that pyproject.toml requires you to prefix pycrucible configuration with tool.pycrucible<.section>.
For example, if setting entrypoint
# pycrucible.toml
entrypoint = "src/main.py"
# or
entry = "src/main.py"
# pyproject.toml
[tool.pycrucible]
entrypoint = "src/main.py"
# or
entry = "src/main.py"
If setting options
# pycrucible.toml
[options]
debug = false
extract_to_temp = false
delete_after_run = false
uv_version = 0.9.21
# pyproject.toml
[tool.pycrucible.options]
debug = false
extract_to_temp = false
delete_after_run = false
uv_version = 0.9.21
Full configuration options can be seen here:
pycrucible.toml
entrypoint = "src/main.py"
# or
entry = "src/main.py"
[options]
debug = false
extract_to_temp = false
delete_after_run = false
uv_version = 0.9.21
[patterns]
include = [
"**/*.py",
]
exclude = [
"**/__pycache__/**",
]
[env]
FOO = "foo"
BAR = "bar"
[hooks]
pre_run = "some_script.py"
post_run = "some_other_script.py"
pyproject.toml
[tool.pycrucible]
entrypoint = "src/main.py"
# or
entry = "src/main.py"
[tool.pycrucible.options]
debug = false
extract_to_temp = false
delete_after_run = false
uv_version = 0.9.21
[tool.pycrucible.patterns]
include = [
"**/*.py",
]
exclude = [
"**/__pycache__/**",
]
[tool.pycrucible.env]
FOO = "foo"
BAR = "bar"
[tool.pycrucible.hooks]
pre_run = "some_script.py"
post_run = "some_other_script.py"
[!TIP] You can use
patternsto include or exclude any arbitrary files, like HTML templates, Kivy layout files or any other arbitrary files needed by your application. For example your flask templates:[tool.pycrucible] entrypoint = "app.py" [tool.pycrucible.patterns] include = [ "**/*.py", "src/templates/*.html", "src/static/*.css", "src/static/*.js", ] exclude = [ "**/__pycache__/**", ]
[!WARNING] There is no need for setting
PYTHONPATHenv variable asuvwill take care of this. If this is really needed,uvwill complain and you should also also setUV_LINK_MODE="copy"as env variable to mitigate the warning.
Default configuration
This configuration takes place when no configuration is set by the user.entrypoint = "src/main.py"
# Options
debug = false # Enable debug output in runner
extract_to_temp = false # Extract contents into temporary directory
delete_after_run = false # Delete contents after running the program
uv_version = "0.9.21" # Select uv version
# Patterns
patterns.include = [
"**/*.py",
]
patterns.exclude = [
".venv/**/*",
"**/__pycache__/**",
".git/**/*",
"**/*.pyc",
"**/*.pyo",
"**/*.pyd"
]
# Source repository (GitHub)
source = None
# Enviroment variables
env = None
# Pre and post run hooks
hooks = None
If any of these configuration options is not used, it will be replaced with default value.
NOTE - entrypoint directive is required when using any configuration options.
[!TIP] As of
v0.4.0PyCrucible supports embedding of.whlfiles. Just give PyCrucible your wheel file instead of source directory and it will take care of the rest.
More PyCrucible options
Running pycrucible --help reveals more options:
$ pycrucible --help
Tool to generate python executable by melding UV and python source code in crucible of one binary
Usage: pycrucible [OPTIONS]
Options:
-e, --embed <SOURCE_DIR> Directory containing Python project to embed.
-o, --output <OUTPUT> Output path for the new binary. If not specified, defaults to `./launcher`.
--uv-path <UV_PATH> Path to `uv` executable. If not found, it will be downloaded automatically [default: .]
--no-uv-embed Disable embedding `uv` binary into the output executable. This will require `uv` to be present alongside (or downloaded) the output binary at runtime.
--extract-to-temp [`wheel` mode only] Extracts the embedded files to a temporary directory instead of a permanent one at runtime. The temporary directory will be deleted when the program exits.
--delete-after-run [`wheel` mode only] Deletes the extracted files after the program finishes running. Ignored if `--extract-to-temp` is used.
--force-uv-download Force re-download of `uv` binary even if it is already present at the specified or default location. Mostly useful for testing purposes.
--debug Enable debug output
-h, --help Print help
-V, --version Print version
Github Action
PyCrucible has associated GitHub Action workflow which you can use to embed your python applications directly in CI.
Security / Code signing
[!WARNING] This is an embedding tool. Like any other tool of this type, it may be used in distribution of un-trusted and/or malicius software.
The builder is the only distributed artifact; the Python projects themselves are provided by developers and has nothing to do with pycrucible or its authors or maintainers. Its is the sole responsibility of the developer and its end-users to confirm authenticity and trust in executing the binary.
Developers, when distributing binary to your end users, please:
- Verify your build environment is clean
- Sign binaries if distributing to external users (after embedding your project)
- Test your output on a clean VM for each platform
- Pin dependencies
- Set reproducible flags
[!IMPORTANT] Make sure you run code signing after embedding your project. This makes sure that embedded project also be part of the signiture.
How PyCrucible works - a diagram
flowchart TD
%% Build Phase
A[PyCrucible CLI Builder] --> B[Is input a .whl file?]
B --> C[Embed wheel as-is]
B --> D[Archive project files]
C --> E[Payload Ready]
D --> E[Payload Ready]
E --> F[Embed uv runtime?]
F --> G[Embed uv]
F --> H[Do not embed uv]
G --> I[Build launcher binary]
H --> I[Build launcher binary]
%% Runtime Phase
I --> J[User runs launcher]
J --> K[Extract payload]
K --> L[Is uv embedded?]
L --> M[Use embedded uv]
L --> N[Locate or download uv]
M --> O[Run with uv]
N --> O[Run with uv]
O --> P[Run project entrypoint]
O --> Q[Run wheel file]
Features
- Cross-Platform:
- Windows support
- macOS support (testing)
- Linux support
- Small overhead:
- Runner binary that embeds your project is just ~2 MB. This ofcourse grows with embedding
uvand your project.
- Runner binary that embeds your project is just ~2 MB. This ofcourse grows with embedding
- Configurable:
- Use
pycrucible.tomlorpyproject.tomlto customize embedding details- entrypoint
- include/exlude files
- arguments to
uv - env variables
- update source code from github
- pre and post run hooks (python scripts)
- extract to temporary directory (removes temporary directory after running automaticly)
- remove extracted files after running
- Support for multiple ways of defining requirements
-
uvinitializedpyproject.toml(This is preffered !) -
requirements.txt -
pylock.toml -
setup.py -
setup.cfg
-
- Load the project as a directory
- Runtime arguments are supported
- Use
- Tests:
- Unit tests covering as much as i can make it
Community
We have an active community on Telegram, you are free to join us.
Changelog
You can see latest changes at
Thanks to
The idea is inspired by Packaged.
Thanks to all the briliant developers at Astral.
They did awesome job with uv.
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 pycrucible-0.4.0-py3-none-win_amd64.whl.
File metadata
- Download URL: pycrucible-0.4.0-py3-none-win_amd64.whl
- Upload date:
- Size: 3.5 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 |
265c5908e07dc8c3067361db108c7073c82206963fe0949437a89d11df5d36f4
|
|
| MD5 |
aca4002b29b7594e4da54209e3c1262d
|
|
| BLAKE2b-256 |
3d41e981b65b8ec75af8be5daf05b3ae4a01d53e7e87872f50908821a3fd4637
|
Provenance
The following attestation bundles were made for pycrucible-0.4.0-py3-none-win_amd64.whl:
Publisher:
v0.3-pipeline.yml on razorblade23/PyCrucible
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycrucible-0.4.0-py3-none-win_amd64.whl -
Subject digest:
265c5908e07dc8c3067361db108c7073c82206963fe0949437a89d11df5d36f4 - Sigstore transparency entry: 820325500
- Sigstore integration time:
-
Permalink:
razorblade23/PyCrucible@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/razorblade23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
v0.3-pipeline.yml@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pycrucible-0.4.0-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: pycrucible-0.4.0-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 3.7 MB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d81cdb0885e2eb84e0bcf380e241a8af01f53c77fede8fbf679ba1658994571f
|
|
| MD5 |
6ce2713800e877681f9fd52bc94c0682
|
|
| BLAKE2b-256 |
8de08d8c834a557a1394be9e37ae4876d7f24f4ec20d0b0f325dcf3f637b38af
|
Provenance
The following attestation bundles were made for pycrucible-0.4.0-py3-none-manylinux_2_28_x86_64.whl:
Publisher:
v0.3-pipeline.yml on razorblade23/PyCrucible
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycrucible-0.4.0-py3-none-manylinux_2_28_x86_64.whl -
Subject digest:
d81cdb0885e2eb84e0bcf380e241a8af01f53c77fede8fbf679ba1658994571f - Sigstore transparency entry: 820325489
- Sigstore integration time:
-
Permalink:
razorblade23/PyCrucible@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/razorblade23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
v0.3-pipeline.yml@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pycrucible-0.4.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: pycrucible-0.4.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.2 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 |
5561cf2dc87e7d3a38efb13cc8030c8ed92d85ec7d2c81f5457f80afc69d22b1
|
|
| MD5 |
20238eeda26e59692fff10ce001c47da
|
|
| BLAKE2b-256 |
eedccf0d6b6c93d049506e6a310541d813caf527b54664fa58c47e78e37b02ad
|
Provenance
The following attestation bundles were made for pycrucible-0.4.0-py3-none-macosx_11_0_arm64.whl:
Publisher:
v0.3-pipeline.yml on razorblade23/PyCrucible
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycrucible-0.4.0-py3-none-macosx_11_0_arm64.whl -
Subject digest:
5561cf2dc87e7d3a38efb13cc8030c8ed92d85ec7d2c81f5457f80afc69d22b1 - Sigstore transparency entry: 820325524
- Sigstore integration time:
-
Permalink:
razorblade23/PyCrucible@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/razorblade23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
v0.3-pipeline.yml@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pycrucible-0.4.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: pycrucible-0.4.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08605dbcf8d7f2dae5a6ff536aac6d1dcad841dc95d5aa90439e8a373350f819
|
|
| MD5 |
bd3c02c11fd464d896f8e526cea56029
|
|
| BLAKE2b-256 |
ece4eac67bdb938ed06a1975cc5f589a193231d6c36a9a626365af4f392c4913
|
Provenance
The following attestation bundles were made for pycrucible-0.4.0-py3-none-macosx_10_12_x86_64.whl:
Publisher:
v0.3-pipeline.yml on razorblade23/PyCrucible
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pycrucible-0.4.0-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
08605dbcf8d7f2dae5a6ff536aac6d1dcad841dc95d5aa90439e8a373350f819 - Sigstore transparency entry: 820325513
- Sigstore integration time:
-
Permalink:
razorblade23/PyCrucible@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/razorblade23
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
v0.3-pipeline.yml@b31e290953ada06de056ba06fa9da0fe0fbc9780 -
Trigger Event:
release
-
Statement type: