pkgx is a 4MB, standalone binary that can run anything.
brew install pkgxdev/made/pkgx || curl https://pkgx.sh | sh
$ deno
command not found: deno
$ pkgx deno
Deno 2.1.4
> ^D
$ deno
command not found: deno
# ^^ nothing was installed; your wider system is untouched$ pkgx node@14 --version
Node.js v14.21.3
$ pkgx python@2 --version
Python 2.7.18-
macOS
- macOS >= 11
- x86-64 & Apple Silicon
-
Windows
WSL2; x86-64. Native windows is planned.
-
Docker
$ pkgx docker run -it pkgxdev/pkgx (docker) $ pkgx node@16 Welcome to Node.js v16.20.1. Type ".help" for more information. >
Or in a
Dockerfile:FROM pkgxdev/pkgx RUN pkgx deno@1.35 task start
Or in any image:
FROM ubuntu RUN curl https://pkgx.sh | sh RUN pkgx python@3.10 -m http.server 8000
-
CI/CD
- uses: pkgxdev/setup@v2 - run: pkgx shellcheck
Or in other CI/CD providers:
curl https://pkgx.sh | sh pkgx shellcheck -
Scripts
#!/usr/bin/env -S pkgx +git python@3.12 # python 3.12 runs the script and `git` is available during its execution
-
Editors
$ cd myproj myproj $ env +cargo (+cargo) myproj $ code .
Or use
dev; a separate tool that uses the pkgx primitives to automatically determine and utilize your dependencies based on your project’s keyfiles.$ cd myproj myproj $ dev env +cargo +rust (+cargo+rust) my-rust-project $ code .
pkgx is not just a package runner, it’s a composable primitive that can be
used to build a whole ecosystem of tools.
dev uses pkgx and shellcode to create “virtual environments” consisting
of the specific versions of tools and their dependencies you need for your
projects.
$ cd my-rust-proj && ls
Cargo.toml src/
my-rust-proj $ cargo build
command not found: cargo
my-rust-proj $ dev
+rust +cargo
my-rust-proj $ cargo build
Compiling my-rust-proj v0.1.0
#…pkgm installs pkgx packages to /usr/local. It installs alongside pkgx.
A powerful use of pkgx is scripting, eg. here’s a script to release new
versions to GitHub:
#!/usr/bin/env -S pkgx +gum +gh +npx +git bash>=4 -eo pipefail
gum format "# determining new version"
versions="$(git tag | grep '^v[0-9]\+\.[0-9]\+\.[0-9]\+')"
v_latest="$(npx -- semver --include-prerelease $versions | tail -n1)"
v_new=$(npx -- semver bump $v_latest --increment $1)
gum format "# releasing v$v_new"
gh release create \
$v_new \
--title "$v_new Released 🎉" \
--generate-notes \
--notes-start-tag=v$v_latestAbove you can see how we “loaded” the shebang with +pkg syntax to bring in
all the tools we needed.
We have pretty advanced versions of the above script, eg teaBASE
There’s tools for just about every language ecosystem so you can import
dependencies. For example, here we use uv to run a python script with
pypi dependencies, and pkgx to load both uv and a specific python version:
#!/usr/bin/env -S pkgx +python@3.11 uv run --script
# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.python.org/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])Tip
We love scripting with pkgx so much that we made a whole package manager
for scripts to show the world what is possible when the whole open source
ecosystem is available to your scripts Check it out mash.
[!INFO] Notably, packages used during your script aren’t installed and don’t pollute your system and anyone else’s systems either. Don’t be confused— they are downloaded to
~/.pkgxbut the wider system is not touched.
Easily run tools from other language ecosystems:
pkgx uvx cowsay "Run Python (PyPi) programs with `uvx`" # or pipx
pkgx bunx cowsay "Run JavaScript (NPM) programs tools with `bunx`" # or `npx`It can be fun to add magic to your shell:
# add to ~/.zshrc
command_not_found_handler() {
pkgx -- "$@"
}Thus if you type gh and it’s not installed pkgx will magically run it as
though it was installed all along.
Note
Bash is the same function but drop the r from the end of the name.
docs.pkgx.sh is a comprehensive manual and user guide for the pkgx
suite.
The pkgx suite has had its scopes tightened. There is no shellcode in pkgx
anymore. Instead dev is its own separate tool that has its own shellcode.
Migrate your shell configuration with:
pkgx pkgx^1 deintegrate
pkgx dev integrateIf you used this, let us know, we can make a mash script to provide this
functionality again. You can achieve the same result as eg. env +git with:
eval "$(pkgx +git)"Surround the eval with set -a and set +a if you need the environment
exported.
We now provide pkgm but if you miss the leanness of “stubs” we provide a
mash script to create stubs in /usr/local/bin:
$ pkgx mash pkgx/stub git
created stub: /usr/local/bin/git
$ cat /usr/local/bin/git
#!/bin/sh
exec pkgx git "$@"
We recommend using dev to make rust available.
- To add packages see the pantry README
- To hack on
pkgxitself; clone it andcargo buildhydrate.rsis where optimization efforts will bear most fruit
cargo fmt --all --check
cargo clippy --all-features
pkgx npx markdownlint --config .github/markdownlint.yml --fix .We love a good chinwag.
