The package exists, but not for you
A tool is in the AUR, or only as a .deb, or only as a GitHub release. Your distro packaged it two years ago, or never.
Zero Layer is a universal Linux package manager. It installs software from 13 different ecosystems onto any distribution by translating binaries at install time — not at run time.
curl -Lo zl https://github.com/supercosti21/zero_layer/releases/latest/download/zl-x86_64-unknown-linux-gnu
Every distribution ships its own format, its own repository and its own idea of where files belong. The software you want is often packaged — just not for your system.
A tool is in the AUR, or only as a .deb, or only as a GitHub release. Your distro packaged it two years ago, or never.
Containers, virtual machines and compatibility layers all solve this by adding a layer. You pay for it forever.
Dropping a tarball into /opt works until a library moves. Nothing tracks the files, and nothing can cleanly undo it.
A Linux binary is not tied to a distribution — it is tied to a handful of concrete facts: which dynamic linker loads it, and where its shared libraries live.
Zero Layer reads those fields with goblin, then rewrites them with elb.
After that the binary is simply a native binary on your machine.
# the ELF fields Zero Layer rewrites ── before ── (built for Arch) PT_INTERP /lib64/ld-linux-x86-64.so.2 RUNPATH (none) NEEDED libpcre2-8.so.0, libc.so.6 ── after ── (patched for this host) PT_INTERP /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 RUNPATH ~/.local/share/zl/lib NEEDED libpcre2-8.so.0, libc.so.6 # same machine code — it just knows # where it lives now
Zero Layer is opinionated. These are the rules the codebase is held to.
All translation work happens once, during installation.
Architecture, linker, libc and layout are probed from the running system.
Every install runs inside a transaction that records what it touched.
redb instead of SQLite, elb instead of patchelf, rustls instead of OpenSSL.
When a package exists in several ecosystems, you choose.
History, rollback, orphan detection and dry-run are core features.
Eight stages run between your command and a working binary. Each one is observable with -v, and any failure rolls the whole thing back.
Finds the package and walks its dependency tree recursively.
Five classes are checked before anything is written.
Packages are fetched over four parallel threads with automatic retry.
SHA256 checksums are enforced and GPG signatures checked.
The archive format is detected, unpacked and normalised to FHS.
Interpreter and RUNPATH are rewritten to match your system.
Files are placed atomically inside a transaction.
Files, dependencies and the operation are written to an embedded database.
Everything you would expect from your distro's tooling, plus the things it never had.
ELF binaries are analysed with goblin and patched with elb at install time.
Every enabled source is queried simultaneously and scored by relevance.
An install either completes or leaves no trace.
doctor, audit, why, size, diff and history answer the questions package managers usually leave you guessing about.
Install versions side by side, or spin up an ephemeral environment.
Checksums and signatures in, CVE lookups against OSV.dev out.
Each source is a plugin implementing the same trait. Enable the ones you want per machine, or filter per command with --from.
Source availability depends on the upstream being reachable. See live plugin status
One binary, twenty-five commands, shell completions for bash, zsh and fish.
$ zl install firefox # pick from every source $ zl install firefox --from pacman # force one source $ zl install sharkdp/bat --from github $ zl install python --version 3.12 # side by side $ zl remove firefox --cascade # drop orphaned deps $ zl --dry-run install firefox # preview only $ zl run neofetch # run without installing
$ zl search vim # all sources, in parallel $ zl search vim --exact # exact names only $ zl search vim --from pacman,apt # limit the sweep $ zl info ripgrep # full metadata $ zl list --explicit # what you asked for $ zl sources list # enabled / disabled $ zl sources only pacman aur github
$ zl doctor # full system health check $ zl why libpcre2 # which package pulled it in $ zl size --sort # disk usage, largest first $ zl diff firefox # what an update would change $ zl audit # known CVEs via OSV.dev $ zl cache dedup # hardlink duplicate libs
$ zl history list # every operation, timestamped $ zl history rollback # undo the last one $ zl history rollback 3 # undo the last three $ zl pin firefox # freeze this version $ zl export # write zl-lock.json $ zl import zl-lock.json # reproduce elsewhere
$ zl env shell # throwaway env, dies on exit $ zl env shell myproject # named, persists $ zl env list $ zl env delete myproject $ zl switch python 3.12 # activate another version $ zl completions zsh # bash · zsh · fish
Predictable layout on disk, pure-Rust dependencies, and a test suite that runs on every push.
Everything lives under one directory you own. Add bin to your PATH and nothing else on the system is touched.
~/.local/share/zl/ bin/ symlinks — add to PATH lib/ shared libraries share/ data files etc/ configuration packages/ one dir per name-version cache/ downloads envs/ ephemeral environments zl.redb package database # nothing outside this tree is modified # removing the folder removes everything
Containers and universal package formats solve the same problem by isolating software. Zero Layer solves it by adapting software.
| Approach | Runtime cost | Disk cost | Needs a daemon | |
|---|---|---|---|---|
| Zero Layer | Patch binaries at install | None | Shared libraries, deduplicated | No |
| Docker / Podman | Full OS image per app | Process + namespace overhead | Image layers per app | Yes |
| Flatpak | Bundled runtimes | Sandbox + portal indirection | Runtime per app family | Yes |
| Snap | Squashfs + confinement | Mount + confinement layer | Compressed image per app | Yes |
| Manual tarball | Unpack and hope | None | Whatever you copied | No |
Manual installs match Zero Layer on overhead — and lose on everything else.
One download, one line in your shell profile. No package manager needed to install the package manager.
Grab the latest release for your architecture. Use the second form if you would rather not use sudo.
$ curl -Lo zl https://github.com/supercosti21/zero_layer/releases/latest/download/zl-x86_64-unknown-linux-gnu $ chmod +x zl && sudo mv zl /usr/local/bin/ # or, without sudo: $ mkdir -p ~/.local/bin && mv zl ~/.local/bin/ # other builds: zl-x86_64-unknown-linux-musl, zl-aarch64-unknown-linux-musl
Zero Layer symlinks the executables it installs into its own bin directory.
# bash (~/.bashrc) or zsh (~/.zshrc) export PATH="$HOME/.local/share/zl/bin:$PATH" # fish fish_add_path ~/.local/share/zl/bin
Leave off --from and Zero Layer will search every enabled source and let you pick.
$ zl install ripgrep $ zl install sharkdp/bat --from github $ zl doctor # confirm everything is healthy
Prefer to build it yourself? Requires Rust 1.85 or newer. cargo build --release →
Free and open source under the MIT licence. No account, no telemetry, no daemon.