-
Notifications
You must be signed in to change notification settings - Fork 0
Package Sources
Zero Layer supports 13 package sources. Each source is a plugin that handles searching, resolving, downloading, and extracting packages from its respective ecosystem. This page documents every source in detail.
- Source Management
- Pacman (Arch Linux)
- AUR (Arch User Repository)
- APT (Debian/Ubuntu)
- DNF (Fedora/RHEL)
- Zypper (openSUSE/SLES)
- APK (Alpine Linux)
- XBPS (Void Linux)
- Portage (Gentoo)
- Nix (nixpkgs)
- GitHub Releases
- Flatpak (Flathub)
- Snap (Snapcraft)
- AppImage (AppImageHub)
- Source Comparison Table
On first run, ZL detects your distro from /etc/os-release and suggests appropriate sources. You can toggle each source on or off with an interactive multi-select menu.
Manage which sources ZL uses at any time:
zl sources list # Show all sources and their status
zl sources enable pacman aur # Enable specific sources
zl sources disable snap flatpak # Disable specific sources
zl sources only pacman aur github # Enable ONLY these, disable everything else
zl sources reset # Remove filter, enable all sourceszl sources list output:
Package Sources
pacman enabled (loaded)
aur enabled (loaded)
apt disabled
github enabled (loaded)
dnf disabled
zypper disabled
apk disabled
xbps disabled
portage disabled
nix disabled
flatpak enabled (loaded)
snap disabled
appimage enabled (loaded)
Active filter: pacman, aur, github, flatpak, appimage
- enabled (green) — ZL will query this source during search/install
- disabled (dim) — ZL will skip this source
- (loaded) — The plugin is initialized and ready (matches your system)
Override the global source list for a single command:
zl search vim --from pacman # Search only pacman
zl search vim --from pacman,apt # Search pacman and apt
zl install vim --from apt # Install from apt specificallyThe --from flag accepts comma-separated source names.
Sources can also be configured in ~/.config/zl/config.toml:
[general]
sources = ["pacman", "aur", "github", "flatpak", "appimage"]When sources is set, only listed sources are loaded at startup. When omitted (or set to null), all sources are enabled.
Individual sources can also be disabled:
[plugins.snap]
enabled = falsePlugin name: pacman
Package format: .pkg.tar.zst, .pkg.tar.xz
Database type: Cached (synced via zl update)
Installs packages from Arch Linux official repositories. Downloads and parses the pacman database files (core.db, extra.db) to search and resolve packages.
zl update --from pacman # Sync the database (required before first use)
zl search firefox --from pacman # Search
zl install firefox --from pacman # Install[plugins.pacman]
mirrorlist = "/etc/pacman.d/mirrorlist" # Path to mirrorlist (auto-detected)
arch = "x86_64" # Architecture (auto-detected)
repos = ["core", "extra"] # Repositories to use-
Sync: Downloads
{repo}.dbfrom the first working mirror. The DB is a tar.gz archive containing package metadata (desc files). - Search: Case-insensitive search across cached package names and descriptions.
-
Resolve: Exact name match first. If not found, checks
providesfields for virtual packages (e.g.,shprovided bybash). -
Download: HTTP download of
.pkg.tar.zstfrom the mirror. - Extract: Decompresses zstd, then extracts tar archive. Classifies files as ELF binaries, scripts, or data.
ZL reads mirrors from /etc/pacman.d/mirrorlist (or the configured path). It uses the first uncommented Server = ... line. If no mirrorlist is found, it falls back to https://geo.mirror.pkgbuild.com.
Each package in the DB provides:
- Name, version, description, architecture
- Dependencies (
depends), optional deps (optdepends) - Provides (virtual packages)
- Conflicts
- Installed size, compressed size
- Download URL (relative to mirror)
Plugin name: aur
Package format: .pkg.tar.zst (built from source)
Database type: Live API queries
Installs packages from the Arch User Repository. Uses the AUR RPC API v5 for search and metadata, then clones the PKGBUILD and builds with makepkg.
zl search yay --from aur # Search the AUR
zl install yay --from aur # Build and install from AURBuilding from AUR requires:
-
git— for cloning PKGBUILDs -
makepkg— for building packages -
base-devel— build tools (gcc, make, etc.)
No specific configuration needed. The AUR plugin uses the public AUR RPC API.
-
Search: Queries
https://aur.archlinux.org/rpc/v5/search/{query}?by=name-desc. Automatically discovers binary variants (-bin,-appimage,-prebuiltsuffixes) and tags them[binary]. -
Resolve: Queries
https://aur.archlinux.org/rpc/v5/info/{name}for exact package metadata. -
Download: Runs
git clone --depth=1 https://aur.archlinux.org/{package_base}.gitinto a temp directory, thenmakepkg --syncdeps --force --noconfirm --noprogressbarto build. -
Extract: The built
.pkg.tar.zstis extracted like a pacman package.
When you search for firefox, ZL also checks for:
-
firefox-bin— precompiled binary -
firefox-appimage— AppImage wrapper -
firefox-prebuilt— prebuilt variant
These are tagged with [binary] in search results so you can choose a precompiled version instead of building from source.
-
Missing base-devel: Install
base-develgroup on Arch first -
PGP key errors: Import the required key with
gpg --recv-keys <KEYID> - Missing dependencies: AUR packages may depend on other AUR packages; ZL resolves these recursively
Plugin name: apt
Package format: .deb (ar archive containing tar)
Database type: Cached index (synced via zl update)
Installs packages from Debian and Ubuntu repositories. Downloads and parses Packages.gz index files.
zl update --from apt # Sync the package index (required)
zl search vim --from apt # Search
zl install vim --from apt # Install[plugins.apt]
mirror = "http://archive.ubuntu.com/ubuntu" # Mirror URL
suite = "noble" # Release codename
components = ["main", "universe"] # Repository components
arch = "amd64" # Architecture (auto-detected)Common suites:
-
Ubuntu:
noble(24.04),jammy(22.04),focal(20.04) -
Debian:
bookworm(12),bullseye(11),trixie(13)
Common mirrors:
- Ubuntu:
http://archive.ubuntu.com/ubuntu - Debian:
http://deb.debian.org/debian
-
Sync: Downloads
{mirror}/dists/{suite}/{component}/binary-{arch}/Packages.gzfor each component. Parses the RFC822-style format into package entries. - Search: Case-insensitive search across cached names and descriptions.
- Resolve: Exact package name lookup with optional version matching.
-
Download: Direct
.debdownload from the mirror. -
Extract:
.debfiles areararchives containingdata.tar.{gz,xz,zst}. ZL extracts the ar, then the inner tar.
| Host arch | APT arch |
|---|---|
| x86_64 | amd64 |
| aarch64 | arm64 |
| arm | armhf |
| i686 | i386 |
| riscv64 | riscv64 |
| powerpc64 | ppc64el |
| s390x | s390x |
Plugin name: dnf
Package format: .rpm
Database type: Cached XML (synced via zl update)
Installs packages from Fedora and RHEL-family repositories. Downloads and parses primary.xml.gz repodata.
zl update --from dnf # Sync the repodata
zl search gcc --from dnf # Search
zl install gcc --from dnf # Install[plugins.dnf]
mirror = "https://dl.fedoraproject.org/pub/fedora/linux"
release = "40" # Fedora release number
repos = ["fedora", "updates"] # Repositories
arch = "x86_64" # Architecture (auto-detected)-
Sync: Downloads
primary.xml.gzfrom each repo:-
fedora:{mirror}/releases/{release}/Everything/{arch}/os/repodata/primary.xml.gz -
updates:{mirror}/updates/{release}/Everything/{arch}/repodata/primary.xml.gz
-
-
Search: In-memory search of parsed
RpmEntrylist (name + summary). - Resolve: Exact name match with version matching.
-
Download: HTTP download of
.rpmfrom the repo. - Extract: RPM extraction — skips lead (96 bytes) and headers, then extracts CPIO payload. Auto-detects compression (gzip, xz, zstd, bzip2).
RPM files have this structure:
[Lead: 96 bytes] [Signature Header] [Main Header] [Compressed CPIO Payload]
The CPIO payload contains the actual files. ZL auto-detects the compression format from magic bytes:
-
1f 8b→ gzip -
fd 37 7a 58 5a 00→ xz -
28 b5 2f fd→ zstd -
42 5a→ bzip2
Plugin name: zypper
Package format: .rpm
Database type: Cached XML (synced via zl update)
Installs packages from openSUSE and SLES repositories. Uses the same RPM extraction as DNF.
zl update --from zypper # Sync the repodata
zl search vim --from zypper # Search
zl install vim --from zypper # Install[plugins.zypper]
mirror = "https://download.opensuse.org"
release = "tumbleweed" # "tumbleweed" or "15.5" for Leap
repos = ["oss", "update"] # Repositories
arch = "x86_64" # Architecture (auto-detected)Different URL patterns for Tumbleweed vs Leap:
-
Tumbleweed:
{mirror}/tumbleweed/repo/{repo}/repodata/primary.xml.gz -
Leap:
{mirror}/distribution/leap/{release}/repo/{repo}/repodata/primary.xml.gz
Plugin name: apk
Package format: .apk (tar.gz)
Database type: Cached index (synced via zl update)
Installs packages from Alpine Linux repositories. Parses the APKINDEX format.
zl update --from apk # Sync the index
zl search curl --from apk # Search
zl install curl --from apk # Install[plugins.apk]
mirror = "https://dl-cdn.alpinelinux.org/alpine"
branch = "v3.20" # Alpine branch
repos = ["main", "community"] # Repositories
arch = "x86_64" # Architecture (auto-detected)-
Sync: Downloads
{mirror}/{branch}/{repo}/{arch}/APKINDEX.tar.gz. Extracts theAPKINDEXfile from the tar.gz and parses the key-value format. - Search: Case-insensitive search in cached entries.
-
Download:
{mirror}/{branch}/{repo}/{arch}/{name}-{version}.apk - Extract: APK files are tar.gz archives. ZL extracts the inner tar.
The APKINDEX file uses a simple key-value format with entries separated by blank lines:
P:curl
V:8.5.0-r0
A:x86_64
T:URL retrieval utility and library
I:245760
D:ca-certificates libcurl
p:cmd:curl
P:vim
V:9.0.2100-r0
...
Key fields:
-
P:— Package name -
V:— Version -
A:— Architecture -
T:— Description -
I:— Installed size (bytes) -
D:— Dependencies (space-separated) -
p:— Provides (space-separated)
Plugin name: xbps
Package format: .xbps (tar.zst)
Database type: Cached
Installs packages from Void Linux repositories.
zl update --from xbps # Sync the repodata
zl search curl --from xbps # Search
zl install curl --from xbps # Install[plugins.xbps]
mirror = "https://repo-default.voidlinux.org"
arch = "x86_64" # Architecture (auto-detected)
repos = ["current", "current/nonfree"] # Repositories-
Sync: Downloads
{mirror}/{repo}/{arch}-repodatafor each repo. -
Extract:
.xbpsfiles are tar archives compressed with zstd.
Note: The repodata parser is currently simplified. XBPS repodata uses a binary plist format. Full plist parsing is planned for a future release.
Plugin name: portage
Package format: .tbz2 (tar+bzip2) or .gpkg.tar
Database type: Cached index (synced via zl update)
Installs binary packages from a Gentoo binhost. Parses the Packages index file.
zl update --from portage # Sync the index
zl search vim --from portage # Search
zl install vim --from portage # Install[plugins.portage]
binhost = "https://distfiles.gentoo.org/releases/amd64/binpackages/17.1/x86-64"
arch = "amd64" # Architecture-
Sync: Downloads
{binhost}/Packagesand parses the key-value block format. - Search: Searches by name, CPV (category/package-version), and description.
-
Extract: Handles both old (
.tbz2) and new (.gpkg.tar) Gentoo binary formats.
CPV: dev-libs/openssl-3.0.12
DESC: Toolkit for SSL and TLS
SIZE: 4521984
PATH: dev-libs/openssl-3.0.12.tbz2
SHA256: abc123...
RDEPEND: sys-libs/zlib dev-libs/libffi
Gentoo uses category/name-version (CPV) format. ZL parses this to extract the package name and version separately.
Plugin name: nix
Package format: .nar (Nix ARchive, optionally compressed with xz or zstd)
Database type: Live API queries
Searches packages from nixpkgs using the search.nixos.org API. Downloads use the Nix binary cache.
zl search ripgrep --from nix # Search nixpkgs[plugins.nix]
channel = "nixos-unstable" # Channel (nixos-unstable, nixos-24.05, etc.)
cache_url = "https://cache.nixos.org" # Binary cache URL-
Search: POST to
https://search.nixos.org/backend/latest-43-{channel}/_searchwith ElasticSearchmulti_matchquery. Searches acrosspackage_pname,package_attr_name, andpackage_description. - Resolve: Searches for exact name match.
-
Download: Currently limited — full NAR download from the binary cache requires narinfo resolution. ZL suggests using
nix profile install nixpkgs#{name}as a workaround.
NAR (Nix ARchive) is Nix's deterministic archive format. ZL includes a complete NAR parser that handles:
- Regular files (with optional executable flag)
- Directories (recursive)
- Symlinks
- Compression:
.nar.xz,.nar.zst, or raw.nar
NAR string encoding: 8-byte little-endian length + content + padding to 8-byte boundary.
Note: Direct NAR download from cache.nixos.org is not yet fully implemented. The NAR parser itself is complete and functional.
Plugin name: github
Package format: tar.gz, tar.xz, tar.zst, zip, AppImage, bare binary
Database type: Live API queries
Installs packages from GitHub Releases. Supports any public repository that publishes release assets.
zl search bat --from github # Search repos
zl install sharkdp/bat --from github # Install (owner/repo format)
zl install BurntSushi/ripgrep --from github # Another example
zl install cli/cli --from github # GitHub CLI itself[plugins.github]
token = "ghp_..." # Optional: personal access token to avoid rate limitingWithout a token, GitHub allows 60 API requests per hour. With a token, 5000 per hour.
-
Search:
GET /search/repositories?q={query}+language:any&sort=stars&per_page=10. Returns the top 10 most-starred matching repos, then fetches the latest release for each. -
Resolve:
GET /repos/{owner}/{repo}/releases/latest(or/tags/{tag}for specific versions). - Download: Direct download of the selected release asset.
- Extract: Auto-detects format from filename/content. Supports tar.gz, tar.xz, tar.zst, zip, AppImage, and bare binaries.
When a release has multiple assets (common), ZL uses a scoring system:
Excluded assets (score = skip):
- Windows assets (
.exe,.msi,windows,win32,win64) - macOS assets (
darwin,macos,.dmg) - Package formats handled by other plugins (
.deb,.rpm,.apk) - Checksum files (
.sha256,.sha512,.md5) - Signature files (
.sig,.asc)
Scoring (lower = better):
- Contains "linux" explicitly: -10
- musl build: -5
- tar.gz: -4
- tar.xz: -3
- tar.zst: -2
- zip: -1
- Bare binary: 0
This means ZL prefers: musl+linux+tar.gz > linux+tar.gz > bare binary > zip.
If you hit GitHub's rate limit (HTTP 429), ZL will tell you:
GitHub API rate limit exceeded. Add a personal access token to config:
[plugins.github]
token = "ghp_..."
Plugin name: flatpak
Package format: Flatpak bundle (managed by flatpak runtime)
Database type: Live API queries
Searches and installs Flatpak applications from Flathub.
zl search firefox --from flatpak # Search Flathub
zl install firefox --from flatpak # Install[plugins.flatpak]
remote = "flathub" # Flatpak remote name-
flatpakCLI must be installed on the system - Flathub remote must be configured (
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo)
-
Search:
GET https://flathub.org/api/v2/search?q={query} -
Resolve:
GET https://flathub.org/api/v2/appstream/{app_id}for app details. -
Install: Delegates to
flatpak install --noninteractive {remote} {app_id}.
Note: Flatpak packages are managed by the Flatpak runtime, not directly by ZL's ELF patching system.
Plugin name: snap
Package format: .snap (SquashFS image)
Database type: Live API queries
Searches and installs Snap packages from the Snapcraft Store.
zl search firefox --from snap # Search the Snap Store
zl install firefox --from snap # Install[plugins.snap]
channel = "stable" # Channel: stable, candidate, beta, edge-
unsquashfs(fromsquashfs-toolspackage) — needed to extract.snapfiles
-
Search:
GET https://api.snapcraft.io/v2/snaps/find?q={query}&fields=title,summary,publisherwith custom headersSnap-Device-Series: 16andSnap-Device-Architecture: {arch}. -
Resolve:
GET https://api.snapcraft.io/v2/snaps/info/{name}— returns channel map with versions for each channel/architecture combination. - Download: Direct download from the URL in the channel map.
-
Extract: Uses
unsquashfsto extract the SquashFS image.
| Host arch | Snap arch |
|---|---|
| x86_64 | amd64 |
| aarch64 | arm64 |
| arm | armhf |
| i686 | i386 |
Plugin name: appimage
Package format: .AppImage (self-contained executable)
Database type: Cached feed (synced via zl update)
Installs AppImage applications from AppImageHub.
zl update --from appimage # Sync the feed
zl search firefox --from appimage # Search
zl install firefox --from appimage # InstallNo specific configuration needed.
-
Sync: Downloads
https://appimage.github.io/feed.json— a JSON file listing all AppImage applications. - Search: In-memory search across app names and descriptions.
- Resolve: Case-insensitive name matching.
-
Download: Direct download from the link in the feed. Sets executable permission (
chmod 0755). -
Install: Places the AppImage in the package's
usr/bin/directory. AppImages are self-contained — they include all libraries and run anywhere.
AppImages don't need ELF patching — they are designed to be portable. ZL simply manages the download, symlink, and tracking.
| Source | Search | Sync Required | Archive Format | External Tools | API |
|---|---|---|---|---|---|
| pacman | Cached | Yes | tar.zst/xz | None | Mirror |
| aur | Live | No | tar.zst | git, makepkg | RPC v5 |
| apt | Cached | Yes | .deb (ar+tar) | None | Mirror |
| dnf | Cached | Yes | .rpm (cpio) | None | Mirror |
| zypper | Cached | Yes | .rpm (cpio) | None | Mirror |
| apk | Cached | Yes | tar.gz | None | Mirror |
| xbps | Cached | Yes | tar.zst | None | Mirror |
| portage | Cached | Yes | tbz2/gpkg | None | Binhost |
| nix | Live | No | .nar | None | ElasticSearch |
| github | Live | No | Various | None | REST API |
| flatpak | Live | No | Flatpak | flatpak | REST API |
| snap | Live | No | SquashFS | unsquashfs | REST API |
| appimage | Cached | Yes | AppImage | None | JSON feed |
Legend:
- Cached: Database/index is downloaded locally for fast offline search
- Live: Queries the remote API on each search (requires internet)
-
Sync Required: Must run
zl update --from <source>before first use
Getting Started
User Guide
Deep Dive
Development
Help