Install programs straight from GitHub releases — no root, no distro packages.
unpin is the CLI installer of the unpins project. It
fetches a program from a GitHub release, verifies its checksum, and either
runs it on the spot or drops it in your PATH.
# Running without a subcommand fetches and runs the program — nothing is installed (the default):
unpin ffmpeg -version
# Install from the curated catalog (a name with no owner resolves to unpins/<name>):
unpin install htop
# Or install from any GitHub release:
unpin install BurntSushi/ripgrepA name with no owner installs from the unpins catalog,
a curated set of common programs that we build as single self-contained
binaries. unpin install jq resolves to unpins/jq
and works the same on Linux, macOS, and Windows. You're not limited to the
catalog: give unpin any owner/repo[@version] and it installs from that
GitHub release.
The official builds are at https://unpins.org. Each platform gets a
single self-contained binary. Download yours, then run unpin install — it
moves the binary into place and offers to add that directory to your PATH:
# Linux
curl -fsSLo unpin "https://unpins.org/unpin-$(uname -m)-linux"
chmod +x unpin
./unpin install
# macOS
curl -fsSLo unpin "https://unpins.org/unpin-$(uname -m)-darwin"
chmod +x unpin
./unpin install# Windows (PowerShell or cmd; needs Windows 10 1803+ for bundled curl)
curl.exe -fsSLo unpin.exe https://unpins.org/unpin-x86_64-windows.exe
.\unpin.exe installunpin install needs no root: it drops the binary in ~/.local/bin
(Linux/macOS) or %LOCALAPPDATA%\unpin (Windows) — a user directory — and only
edits your PATH after asking. Open a new shell for the change to take effect.
Linux builds cover six architectures — x86_64, aarch64, armv7l, i686, ppc64le,
and riscv64; macOS builds cover Intel and Apple Silicon; Windows is x86_64.
The $(uname -m) in the URL picks the right one.
Every build has a .sha256 file at the same URL with .sha256 appended —
compare it against sha256sum unpin (Linux), shasum -a 256 unpin (macOS),
or CertUtil -hashfile unpin.exe SHA256 (Windows) to verify the download.
cargo install --git https://github.com/unpins/unpin --lockedThis builds unpin from the latest commit and drops it in ~/.cargo/bin.
Requires a Rust toolchain (edition 2024, MSRV matches the latest stable).
Native TLS uses an embedded mbedtls build, so cmake, perl, python3,
and libclang need to be available — install them through your package
manager if cargo install complains.
One caveat: the opt-in DNS fallback is
linked into the official binaries by the Nix build — a Cargo build doesn't
include it, so UNPIN_DNS and the dns config key have no effect there.
nix build github:unpins/unpin
./result/bin/unpin --versionThe flake outputs self-contained binaries for Linux/macOS and a cross-built .exe for
Windows. See flake.nix for the build matrix.
unpin [run] <repo> [args...] Fetch and execute a binary without linking (default command)
unpin install Self-install: move this binary into place and add it to PATH
unpin install <repo>... Install one or more packages onto PATH
unpin update [<name>...] Pull newer releases (all packages if no names)
unpin uninstall [<name>...] Uninstall packages (all but unpin if no names; --all includes unpin)
unpin list List installed packages
unpin info <name>... Show details for packages (installed or not)
unpin man [<name>] [page] Render a program's embedded manual page, paged
unpin readme [<name>] Render a program's README, paged
unpin clean Remove dangling links and unused versions
unpin completion <shell> Print a shell completion script
Running without a subcommand runs the program; installing onto PATH is the
explicit unpin install. The doc verbs render what a program carries inside
itself — unpin man coreutils ls renders coreutils' embedded manual page and
unpin readme htop renders htop's README. Both are built in, paged, and (for
man) offline; they reflow as you resize the window.
Common flags:
| Flag | Meaning |
|---|---|
-y, --yes |
Skip confirmation prompts |
-j N, --jobs N |
Parallel workers for download + extract (default: one per package, max 4) |
--pick |
Always prompt when multiple release assets match |
-v, --verbose |
Print every HTTP request and the release assets filtered out |
-V, --version |
Print unpin <version> |
A <repo> is owner/name[@version]. When the owner is omitted, unpins is
assumed — so unpin install htop resolves to unpins/htop. When @version
is omitted, the latest release is used.
On a host that can't reach any DNS server — Android has no /etc/resolv.conf,
a barebones container may ship none, a nameserver may be dead or blocked —
downloads fail with a resolver error. unpin and every program from the catalog
can resolve through a public DNS server instead, but that fallback is off by
default: it never second-guesses a working resolver, and even when enabled it
only kicks in when the system resolver can't be reached at all. On such a
failure unpin prints a short hint with both ways to turn it on:
# one run:
UNPIN_DNS="1.1.1.1 8.8.8.8" unpin install htop
# always — add to unpin's config file (~/.config/unpin/config on Linux/macOS,
# %APPDATA%\unpin\config on Windows); every unpins program honours it, not
# just unpin:
dns = 1.1.1.1 8.8.8.8The value is a space-separated list of IPv4 literals, tried in order over
UDP/53 and then DNS-over-HTTPS for networks that also block port 53.
UNPIN_DNS overrides the config for a single run.
unpin completion <shell> prints a script that hooks the binary into your
shell's completion. Generated dynamically by the parser, so it always matches
the installed version's commands and flags.
# bash
unpin completion bash > ~/.local/share/bash-completion/completions/unpin
# zsh — add ~/.zfunc to fpath in ~/.zshrc, then:
unpin completion zsh > ~/.zfunc/_unpin
# fish
unpin completion fish > ~/.config/fish/completions/unpin.fish
# elvish
unpin completion elvish >> ~/.config/elvish/rc.elvStart a new shell session to pick up the completion.
MIT. Packaged programs keep their upstream licenses — see the packages page.