Bundle Python projects and all pip dependencies into a portable archive for offline, air-gapped deployment.
Project description
VenvDrop
Deploy massive Python environments — torch, llama_cpp, anything — to completely offline, air-gapped machines. Then wirelessly beam the archive to any machine on the same network, AirDrop-style.
VenvDrop uses the Offline Wheelhouse method: download all your pip dependencies as pre-built binary wheels on an internet-connected machine, bundle them with your source code into a single portable .zip, transfer it to the target, and deploy in one command — entirely offline.
Installation
pip install venvdrop
venvdrop --version # venvdrop 0.2.0
venvdrop --commands # full command cheat sheet
venvdrop --help # overview
Quick Start
1 — Pack (internet machine)
# Standard: download wheels fresh from PyPI
venvdrop pack -r requirements.txt -s . -o my_app.zip
# Faster: reuse your existing venv — no re-download needed
venvdrop pack -r requirements.txt -s . -o my_app.zip --from-venv .venv
2 — Transfer to the offline machine
Option A — AirDrop-like wireless (same Wi-Fi / LAN):
# Machine A (has the zip):
venvdrop send -a my_app.zip
# Machine B (offline target) — at the same time:
venvdrop receive -d ./
Option B — Manually copy my_app.zip via USB, SCP, or shared drive.
3 — Deploy (offline machine)
venvdrop unpack -a my_app.zip -d ./deployed_app
4 — Activate and run
# Windows
.\deployed_app\venv\Scripts\activate
# Linux / macOS
source ./deployed_app/venv/bin/activate
Commands
venvdrop pack — Create a portable archive
Downloads all pip dependencies as pre-built binary wheels, scans source for portability issues, embeds platform metadata, generates a SHA-256 integrity manifest, and zips everything into one self-contained archive.
| Flag | Short | Default | Description |
|---|---|---|---|
--requirements |
-r |
requirements.txt |
pip requirements file |
--source |
-s |
. |
Project source root |
--output |
-o |
app_bundle.zip |
Output archive name |
--from-venv |
(none) | Reuse an existing venv's pip wheel cache instead of downloading |
Auto-excluded from source: venv/, .venv/, .git/, __pycache__/, node_modules/, dist/, build/, *.pyc, *.pyd, *.so, *.dll
What happens:
- AST-scans every
.pyfile for hardcoded absolute paths — warns before bundling - Downloads (or reuses) all pip dependency wheels into
bundle_cache/ - Warns if any
.tar.gzsource distributions are found (they need a compiler on target) - Embeds platform metadata →
bundle_meta.json(Python version, OS, CPU arch) - Generates SHA-256 checksums for every file →
manifest.json - Zips
bundle_cache/+source/+requirements.txt+ metadata into the output
# Examples
venvdrop pack -r requirements.txt -s . -o my_app.zip
venvdrop pack -r requirements.txt -s ./src -o releases/v1.2.zip --from-venv .venv
venvdrop unpack — Deploy on the offline machine
Validates platform compatibility, verifies bundle integrity, creates a fresh virtual environment, and installs everything offline.
| Flag | Short | Default | Description |
|---|---|---|---|
--archive |
-a |
(required) | Path to the .zip from venvdrop pack |
--dest |
-d |
./deployed_app |
Destination directory |
What happens:
- Reads
bundle_meta.json— validates OS, CPU arch, Python version - Auto-discovers compatible Python interpreter if version mismatches (prompts if not found)
- Windows MAX_PATH guard: warns if destination path > 200 chars
- Venv collision handling — interactive: Overwrite / Backup / Abort
- Extracts archive and verifies SHA-256 of every file
- Creates a fresh
venv/with the correct Python interpreter - Upgrades pip inside the new venv (prevents PEP 517 issues)
- Installs all packages offline:
pip install --no-index --find-links bundle_cache/ - Prints post-install checklist for system-level deps (CUDA, VC++ Redist, etc.)
# Examples
venvdrop unpack -a my_app.zip
venvdrop unpack -a my_app.zip -d C:\app # Windows short path
venvdrop unpack -a my_app.zip -d /opt/myapp # Linux/macOS
venvdrop send — Wirelessly send an archive (AirDrop-like)
Announces the archive on the local network via UDP multicast so any venvdrop receive instance on the same Wi-Fi or LAN can discover and download it automatically.
| Flag | Short | Default | Description |
|---|---|---|---|
--archive |
-a |
(required) | Archive to send |
What happens:
- Computes SHA-256 of the archive
- Generates a random 4-digit PIN (shown prominently on screen)
- Starts an HTTP file server on a local port (8900–8999)
- Broadcasts a UDP multicast beacon every second — receivers discover it automatically
- Streams the file with a live progress bar when a receiver connects
- Shuts down cleanly after transfer or on Ctrl+C
venvdrop send -a my_app.zip
# Note the PIN displayed and tell it to the receiver
venvdrop receive — Wirelessly receive an archive
Listens for venvdrop send beacons on the LAN, shows discovered senders, and downloads with a live progress bar.
| Flag | Short | Default | Description |
|---|---|---|---|
--dest |
-d |
./received |
Where to save the file |
--timeout |
30 |
Seconds to scan for senders |
What happens:
- Listens on UDP multicast for sender beacons
- Displays each discovered sender (filename, size, IP address)
- Prompts for the 4-digit PIN shown on the sender's terminal
- Downloads via HTTP with a live ANSI progress bar
- Verifies SHA-256 integrity after download — fails loudly if tampered
venvdrop receive # scan 30s, save to ./received
venvdrop receive -d C:\transfers # custom destination
venvdrop receive --timeout 60 # scan longer
Global Flags
| Flag | Short | Description |
|---|---|---|
--help |
-h |
Show help for any command |
--version |
-V |
Print installed version (venvdrop 0.2.0) |
--commands |
-c |
Full color-coded cheat sheet of all commands + examples |
venvdrop --commands # prints the full reference sheet
venvdrop pack --help # detailed help for a specific subcommand
What Problems Does VenvDrop Solve?
| Problem | How VenvDrop Handles It |
|---|---|
| No internet on target machine | Downloads wheels upfront; installs with --no-index |
| Re-downloading wheels is slow | --from-venv reuses pip's local wheel cache — no download |
| Source distribution / compile trap | Detects .tar.gz sdists and warns: use --only-binary=:all: |
| Hardcoded absolute paths | AST-scans every .py file and warns before bundling |
| Python version mismatch | Auto-discovers the right interpreter; prompts if not found |
| OS / arch mismatch | Blocks deployment if wheels won't run (e.g. x86_64 → ARM) |
| Windows MAX_PATH (260 chars) | Warns if destination path > 200 characters |
| Windows command-line too long | Wheels staged into one flat dir; single --find-links arg |
| No USB / cable to transfer | venvdrop send + venvdrop receive over LAN — no cable needed |
| Transfer corruption | SHA-256 manifest verified on unpack; SHA-256 re-checked on receive |
| Existing venv collision | Interactive: Overwrite / Backup / Abort |
| Outdated pip in new venv | Bootstraps pip install --upgrade pip before offline install |
| Missing system drivers | Post-install checklist: CUDA, VC++ Redist, OpenSSL, ODBC |
Why Not Just Copy the venv Folder?
Copying a venv directory breaks because:
- Absolute paths baked into scripts and
.pthfiles point to the source machine - Native extensions (
.pyd,.so) are compiled for a specific OS + arch - The Python interpreter path inside the venv is hardcoded
VenvDrop creates a fresh venv on the target machine and populates it from pre-built wheels, so all paths are correct from the start.
Troubleshooting
| Issue | Fix |
|---|---|
| sdist warning during pack | Re-run pip download with --only-binary=:all: |
| Python version mismatch | Install required Python on target; VenvDrop will prompt for path |
| OS / arch mismatch on unpack | Pack on a machine that matches the target OS and CPU |
| Windows MAX_PATH error | Choose a shorter --dest, e.g. C:\app |
bundle_meta.json missing |
Archive wasn't created by VenvDrop; re-pack |
| Integrity check failures | Archive was corrupted in transit; re-transfer or re-send |
--from-venv can't find Python |
Pass the venv ROOT (folder containing Scripts/ or bin/) |
venvdrop receive finds no senders |
Ensure both machines are on the same Wi-Fi/LAN; check firewall |
| Wrong PIN on receive | Sender rejects the connection — check the PIN on sender terminal |
Requirements
- Python ≥ 3.8
- Zero runtime dependencies — pure Python stdlib only
Development
git clone https://github.com/sasidharakurathi/venvdrop.git
cd venvdrop
pip install -e . # editable install — changes to .py files apply immediately
venvdrop --version
venvdrop --commands
See CONTRIBUTING.md for full dev guide and PyPI release steps.
License
MIT — see LICENSE. Copyright © 2025 Sasidhar Akurathi.
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 venvdrop-0.2.0.tar.gz.
File metadata
- Download URL: venvdrop-0.2.0.tar.gz
- Upload date:
- Size: 34.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e101574d76f0b1dac4b49e4321ad781ca8421b7492ecb80b47435805e50cbf63
|
|
| MD5 |
b7aab5809daee3052347e5fedba17745
|
|
| BLAKE2b-256 |
05ea1b0bf15d65bf9c6d70be9c32771c104bacec6b86c2428144794948fb45c0
|
File details
Details for the file venvdrop-0.2.0-py3-none-any.whl.
File metadata
- Download URL: venvdrop-0.2.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e34876f0ab0d8b2ee39a4d5463e250ff0d272a845668a326fba4e6e03c5bae04
|
|
| MD5 |
c575d13848b6a5d49e9095f93a760b0a
|
|
| BLAKE2b-256 |
c88166f471fdb537b804386ea2ecd4d7f69b38fb6709ad269d85839b7909d0b9
|