PyCrucible docs
PyCrucible
"Run Python Apps Instantly, No Setup Required."
A robust, cross-platform embedder for Python applications using uv for bootstraping.
Overview
This tool runs a Python application with a help of UV binary. It extracts your application, loads an optional configuration from pycrucible.toml or pyproject.toml, and uses uv to run your app in an ephemeral environment.
What this means?
What this means is that you get a single binary, which can then be transfered to other machines running the same platform.
Only internet connection required. No python installation needed. You run the executable and it takes care of everything.
How to get PyCrucible
There are a couple of ways to get PyCrucible.
Using PyPI
PyCrucible is published to PyPI for every release. All you need to do is:
pip install pycrucible
Using Github Releases
You can download pre-made binaries for your system from Github Releases page
Downloading and building the source code
Ensure you have Rust installed.
Clone the repository
git clonehttps://github.com/razorblade23/PyCrucibleChange directory to be inside of a project
cd PyCrucibleBuild the binary
cargo build --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.
Run pip install pycrucible. This will download and install PyCrucible.
Change directory into your project and run
Linux and MacOS
pycrucible -e . -o -/launcher
Windows
pycrucible -e . -o -/launcher.exe
This will embed your project and produce a new binary which we called launcher (or launcher.exe on Windows).
This is now all you need to distribute your python project to other people.
No python required on their end. Just this single binary.
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 <EMBED>
Directory containing Python project to embed. When specified, creates a new binary with the embedded project
-o, --output <OUTPUT>
Output path for the new binary when using --embed
--uv-path <UV_PATH>
Path to `uv` executable. If not found, it will be downloaded automatically [default: `.`]
--extract-to-temp
Extract Python project to a temporary directory when running
--debug
Enable debug output
--delete-after-run <DELETE_AFTER_RUN>
Delete extracted files after running. Note: requires re-downloading dependencies on each run [default: false]
-h, --help
Print help
-V, --version
Print version
How to configure PyCrucible
Configuration can be set in two ways:
pycrucible.tomlpyproject.toml
[!NOTE] When both
pycrucible.tomlandpyproject.tomlare discovered, configuration frompycrucible.tomlwill take effect.[!IMPORTANT] When using any configuration, only
entrypointis required. Other options are optional.[!TIP] In both
pycrucible.tomlandpyproject.tomldirectiveentrypointcan also be replaced by justentry.
Both of these files have exact same configuration options. You can find example file for pycrucible.toml here
In pycrucible.toml you would define configuration like this:
entrypoint = "src/main.py"
# or
entry = "src/main.py"
[package.patterns]
include = [
"**/*.py",
]
exclude = [
"**/__pycache__/**",
]
[hooks]
pre_run = "some_script.py"
post_run = "some_other_script.py"
In pyproject.toml you would define configuration like this:
[tool.pycrucible]
entrypoint = "src/main.py"
# or
entry = "src/main.py"
[tool.pycrucible.patterns]
include = [
"**/*.py",
]
exclude = [
"**/__pycache__/**",
]
[tool.pycrucible.hooks]
pre_run = "some_script.py"
post_run = "some_other_script.py"
Update your project from GitHub
In configuration file its possible to set your GitHub repository, so the resulting binary will always check for update before running the application.
In pycrucible.toml it would look like this:
[source]
repository = "https://github.com/username/repo"
branch = "main"
update_strategy = "pull"
In pyproject.toml it would look like this-
[tool.pycrucible.source]
repository = "https://github.com/username/repo"
branch = "main"
update_strategy = "pull"
Default configuration
entrypoint = "main.py"
patterns.include = [
"**/*.py",
]
patterns.exclude = [
".venv/**/*",
"**/__pycache__/**",
".git/**/*",
"**/*.pyc",
"**/*.pyo",
"**/*.pyd"
]
source = None
uv = None
env = None
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.
Features
Cross-Platform:
[x] Windows support
[x] macOS support (testing)
[x] Linux support
Configurable:
[ ] Use
pycrucible.tomlorpyproject.tomlto customize embedding details[x] entrypoint
[x] include/exlude files
[ ] arguments to
uv[ ] env variables
[x] pre and post run hooks (python scripts)
[ ] offline mode
[ ] extract to temporary directory
[ ] remove extracted files after running
[x] Support for multiple ways of defining requirements
[x]
uvinitializedpyproject.toml[x]
requirements.txt[x]
pylock.toml[x]
setup.py[x]
setup.cfg
[x] Load the project as a directory
[ ] Load the project as .zip archive
Tests:
- [x] Unit tests cover configuration, extraction, and hook execution
Source Update:
- [x] Initiate an update of source code pulling from GitHub
Thanks to
The idea is inspired by Packaged.
Thanks to all the briliant developers at Astral - they did awesome job with uv