lx builds installable packages from many kinds of upstream: forge
release binaries (GitHub, GitLab, Gitea, Forgejo, Bitbucket, Gerrit),
source compilation, language package registries (npm, pip, gem), or files
you supply directly. Output is real Debian packages (.deb), RPM
(.rpm), or Arch (.pkg.tar.zst) — full dependency relations,
epoch-aware versioning, man pages and license files at their conventional
FHS paths — built natively on bare metal with no containers, no
emulation, no Debian host required.
It also installs/upgrades/removes the packages it builds — an apt-like
front end for software that ships forge releases, plus the tooling to run
a prebuilt apt repository from its output. It's a Rust rewrite of the
debian-multiarch-builder
GitHub Action, usable as a local CLI (lx, with the lx get consumer
subcommand), as a GitHub Action (action.yml, see the guide),
and as a repo publisher (lx repo).
It's also host-aware: lx auto-detects the OS, architecture, package
manager, and native package format it's running on, then defaults each
command to suit — one CLI, no per-distro runbook.
Full docs live in docs/:
- Commands — every subcommand and flag
package.yamlreference — all config fields- Host detection — the smart-defaults table
- Package indexes —
lx index, repology, coverage - GitHub Action · Reproducible builds
- Architecture — plugin dimensions, catalog, tooling
- Evaluations — Interoperability · Composability
- Comparisons · Landscape · Decisions
-
Rust (to build
lxitself; see Development). That's it —lxbuilds natively on bare metal:lx buildwrites.debs in-process (lib/debarchive.rs); nodpkg-deb, no Debian toolchain, and cross-architecture packaging only copies/chmods the target binary — it's never executed, so any host can package any architecture.--sourcewrites source packages (.dsc/.orig.tar.xz/.debian.tar.xz) in-process too — nodpkg-source.--lintianshells out to alintianbinary on yourPATH(e.g.apt-get install lintianon Debian/Ubuntu): the one external tool with no Rust equivalent.
See
docs/decisions/2026-08-20-docker-free-deb-build.mdanddocs/decisions/2026-08-20-docker-free-lintian-source.mdfor how, and the trade-offs involved.
Build every architecture a forge release publishes, no config file needed:
lx build https://github.com/eza-community/ezaBuild for just this machine's own architecture (native-only):
lx build package.yaml --hostPackage files you supply — no forge release, minimal config (fpm-style "you supply files" mode):
lx build --from-dir ./myapp-dist/ --package-name myapp --version 1.0.0
lx build --from-file ./myapp --package-name myapp --version 1.0.0
lx build --from-dir ./dist/ --package-name myapp --version 1.0.0 --prefix /usr/local/binWith a base package.yaml for extra metadata (dependencies, contents,
signing, etc.):
lx build package.yaml --from-dir ./myapp-dist/Package from a language registry (input source plugin), via package.yaml:
# package.yaml — npm example
package_name: typescript
registry_source: npm
github_repo: typescript # npm package name
version: latest # optionallx build package.yamlGenerate a package.yaml interactively, with auto-discovered release
patterns:
lx initOr scaffold one non-interactively from a forge repo (auto-discovers the release assets) or a bundled debian-multiarch-builder template:
lx init --from eza-community/eza # discover + write a starter package.yaml
lx init --template rust/eza # or go/hugo, c/neovim, python/generic, …(An unknown name lists all of them; see templates/README.md.)
cargo build
cargo test
cargo clippy --all-targets --all-features -- -D warnings
cargo fmt --allPre-commit hooks (.pre-commit-config.yaml) run fmt/clippy/rust-only
policy/secret scan/license check/typos on every commit, and the fuller
cargo test + coverage gate + cargo deny + doc lint on push. The hooks
are implemented by the Rust cargo xtask runner — this repo has no shell
scripts:
make dev-setup # install hook binaries (idempotent)
pre-commit install
pre-commit install --hook-type pre-pushDeveloper tasks live in the Rust cargo xtask runner (--help lists them):
policy, license-check, secret-scan, coverage, func-tests, bench,
and dev-setup.
See CONTRIBUTING.md for the full setup guide, hook reference, and project layout.
Performance comparisons against the tools lx replaces (dpkg-deb,
dpkg-shlibdeps, dpkg-scanpackages, fpm, nfpm, …) live in
benchmarking/: the
benchmark catalogue lists what to record,
cargo xtask bench reproduces the automated rows, and
results.md keeps the records.
docs/decisions/ records the non-obvious calls
made while porting from the bash action (library choices, config-format
decisions, investigation notes) — worth a look before changing behavior
that mirrors upstream.