pkgx
is a 4MB, standalone binary that can run anything.
brew install pkgxdev/made/pkgx || sh <(curl https://pkgx.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_latest
Above 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
.
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 integrate
If 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
pkgx
itself; clone it andcargo build
hydrate.rs
is 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.