Python Downloader (pronounced "piddle"). A small CLI that fetches, verifies and runs the standalone Python distributions published by astral-sh/python-build-standalone — no system Python, no apt/brew, no PPA.
Pick a tag and version, download it once, use it forever:
pydl update # one-time refresh of the local snapshot
pydl available -v 3.14.4 # offline: read from the snapshot
pydl download -t 20260414 -v 3.14.4 # one-time network hit for the asset
pydl python -t 20260414 -v 3.14.4 -- -m venv .venv
. ./.venv/bin/activate- No system Python required. Downloads self-contained distributions that run without package-manager coordination. Useful for CI images, air-gapped machines or just avoiding conflicts with your OS Python.
- Reproducible. Every asset is verified against a SHA-256 baked into the
pydlbinary at build time. Checksums are committed alongside the code, so two people running the samepydlon the same(tag, version)get bit-identical bytes. - Predictable network usage. Only
pydl update,pydl downloadandpydl self-updatetouch the network. Of those,pydl updateis the only one that contactsapi.github.comfor release listings (whichpydl self-update --onlinealso does);pydl downloadandpydl self-updatealways reach out for asset bytes. Everything else —available,install,python,pin,uninstall,installed,cache,completions— is guaranteed offline and fast. - Project-pinned builds.
pydl pinwrites a.pydl.jsonfile you can commit; teammates who runpydl python -- …in the repo pick up the same Python build automatically.
pydl update is the single command that fetches the upstream releases list and the latest pydl version, writing both to ~/.pydl/snapshot/. pydl available and pydl self-update read from that snapshot — they never contact api.github.com. If no snapshot is present, those commands error with a hint to run pydl update first; if the snapshot is older than 7 days they additionally suggest a refresh. Pass --online to pydl self-update for a one-off bypass that hits the network directly.
macOS / Linux / WSL
curl -fsSL https://raw.githubusercontent.com/rcook/pydl/main/install.sh | shWindows (PowerShell)
irm https://raw.githubusercontent.com/rcook/pydl/main/install.ps1 | iexWindows (CMD)
curl -fsSL https://raw.githubusercontent.com/rcook/pydl/main/install.ps1 -o %TEMP%\pydl-install.ps1 && powershell -ExecutionPolicy Bypass -File %TEMP%\pydl-install.ps1Default install location is ~/.local/bin (Unix) or %LOCALAPPDATA%\Programs\pydl (Windows); override with the PYDL_INSTALL_DIR environment variable. Make sure the install directory is on your PATH.
You can also grab a release archive manually from the Releases page. Once installed, pydl self-update keeps the binary current.
rustup(which providescargo). The pinned toolchain inrust-toolchain.tomlinstalls the right stable channel — includingclippyandrustfmt— automatically the first time you runcargo.- macOS:
brew install rustup(or use the script from https://rustup.rs). - Debian/Ubuntu:
sudo apt install pkg-config rustup && rustup default stable.
- macOS:
nightlyrustfmt for the import-grouping options inrustfmt.toml— only needed if you'll run./dev.sh fmt/fmt-check:rustup toolchain install nightly --profile minimal --component rustfmt
For full contributor setup see DEV.md.
git clone <this-repo>
cd pydl
./dev.sh install-pydl # builds in release mode, copies to ~/.local/bin/pydl~/.local/bin on PATH → pydl is available in any shell. If ~/.local/bin isn't on your PATH, the installer warns you and the copy still succeeds — add the dir to your shell config (export PATH="$HOME/.local/bin:$PATH") and reload.
See pydl/README.md for the full user guide — subcommands, filter flags, the .pydl.json pin file and every supported workflow.
Quick orientation (every command accepts -C <DIR> to run as if started in that directory — see pydl/README.md for details):
| Command | Network? | What it does |
|---|---|---|
pydl update |
yes | Refresh ~/.pydl/snapshot/ (Python releases list + latest pydl version). The only listings hit. |
pydl available |
no | Show what's available from the local snapshot — Python releases plus the latest pydl version. |
pydl download |
yes | Fetch one asset into ~/.pydl/cache/. |
pydl install |
no | Verify + unpack a downloaded asset into ~/.pydl/asset/<hash>. |
pydl installed |
no | List what's installed locally. |
pydl uninstall |
no | Remove an installed asset. |
pydl python -- … |
no | Run a previously-installed interpreter. |
pydl pin |
no | Freeze tag/version into .pydl.json for the project. |
pydl status |
no | Report pin and asset state for the working directory. |
pydl cache |
no | Inspect or clear the HTTP cache. |
pydl completions |
no | Emit a shell-completion script. |
pydl self-update |
always | Replace the running binary with the latest GitHub release. Reads the version from the snapshot by default; --online bypasses it. The binary itself is always downloaded over the network. |
Everything pydl writes lives under ~/.pydl/ (Unix) or %USERPROFILE%\.pydl\ (Windows):
snapshot/— JSON snapshots written bypydl update(pbs-releases.json,pydl-latest.json).cache/— HTTP-cache bodies for downloaded assets.asset/<hash>/— unpacked Python distributions.
All three are safe to delete; the next pydl update rebuilds the snapshot, and the next pydl download / pydl install rebuilds the cache and asset directory. pydl cache clear --yes and pydl uninstall --all --yes do the corresponding cleanups through the CLI.
pydl/README.md— the user guide (subcommands, flags,.pydl.json, examples).DEV.md— contributor guide (workspace layout, build/test/lint workflow, CI, how to refresh the embedded checksum set, how to add a new crate).DESIGN.md— whypydlverifies assets the way it does (threat model, alternatives considered).ISSUES.md— rolling triage of bugs, smells and resolved investigations across the workspace.- Library READMEs:
pydl-cache(the pull-through HTTP cache),get-checksums(maintenance tool to populate./checksums/),check-checksums(CI trip-wire).