libalpm (default)
The library behind pacman.
Nothing to configure or migrate: repositories, locks, keyrings and caches are exactly the ones
pacman already uses on your system.
A package backend is the engine Shelly uses to read repositories, resolve dependencies and apply
package transactions. Shelly ships two of them and builds both by default: libalpm, the C library
behind pacman, is the default, so nothing changes unless you opt in. The alternative is RLPM, the
Rolling Linux Package Manager, Shelly’s own native package engine written in Zig. Builds that
include both engines can select either through a configuration setting. Dedicated RLPM-only
builds, including the Arch and Devario recipes, default to RLPM and cannot select libalpm.
Most systems are served by the default. Pick an engine based on how you want transactions to run under the hood:
libalpm (default)
The library behind pacman.
Nothing to configure or migrate: repositories, locks, keyrings and caches are exactly the ones
pacman already uses on your system.
RLPM
Shelly’s own native engine, written in Zig.
Repositories, dependency resolution and transactions are implemented natively, with no libalpm
dependency at all. It supports both traditional pacman tar databases and in-memory SQLite
databases alongside runtime x86_64_v2/v3/v4 architecture detection, and powers RLPM-only
builds.
The active engine is the NativePackageBackend entry in your CLI configuration
(~/.config/shelly/config.json), so the standard shelly config commands are all you need:
shelly config get NativePackageBackendThis prints libalpm or rlpm. On a default installation the answer is libalpm.
shelly config set NativePackageBackend rlpmThe setting takes effect on the next CLI invocation, not inside an already-running session. The desktop app has no separate switch: it runs the engine the CLI is set to.
On a build that includes libalpm, switch back the same way:
shelly config set NativePackageBackend libalpmOn the standard Arch path profile, switching engines preserves the configured package locations and uses a compatible installed database format. This does not imply identical behavior in every transaction or failure case:
pacman.conf is still read for repositories and paths, and path
defaults stay on the standard pacman profile: /etc/pacman.conf, /var/lib/pacman,
/var/cache/pacman/pkg and the standard keyring and hook directories./var/lib/pacman, in the format both engines
read and write.db.lck transaction lock, so pacman and Shelly still
cannot run transactions at the same time.For how this native configuration relates to Shelly’s CLI settings and the separate
shellybuild.conf used by shelly build, see the
configuration guide.
Where libalpm calls into Arch’s C library, RLPM re-implements the engine natively. The
differences you can observe:
libalpm. Repository
handling, dependency resolution and transactions are Shelly’s own Zig implementation.
RLPM-only builds omit libalpm linkage; dual-backend binaries still load their compiled dynamic
dependencies even when RLPM is selected.pacman.db member is read as
SQLite directly in memory (sqlite3_deserialize), with no member extracted to disk, alongside
ordinary tar repositories.Architecture = auto expands through detected CPU and OS
capabilities into the ordered x86_64, x86_64_v2, x86_64_v3, x86_64_v4 set, selecting the
highest supported microarchitecture tier.%INSTALLED_DB%), and that record survives even after the repository is removed from the
configuration.memfd_create) before verification, preventing time-of-check to time-of-use (TOCTOU)
modifications so the bytes GPG and the archive reader inspect cannot change afterwards. Checksums
prefer SHA-256 over MD5, and an enabled embedded signature supersedes repository digests.NetworkAccess=allowed, and administrators can lift isolation
with DisableSandboxNetwork (or DisableSandbox) in the native package configuration
(pacman.conf or shelly.conf, depending on the path profile); the programmatic API exposes this
as sandbox.disable_network.openat2 with
RESOLVE_IN_ROOT | RESOLVE_NO_MAGICLINKS, ensuring symlink resolutions stay confined to the held
root directory descriptor without path traversal risks.check_space applies a native safety cushion (the smaller of
roughly 5% capacity and 20 MiB) and accounts for staging, directory overhead, and database
journals, catching capacity issues before payload mutations.RLPM runs the same transaction lifecycle you know from libalpm, in five stages:
┌─────────────────────────────────────────────────────────────┐│ 1. Load and verify databases ││ • Local and sync snapshots under the held lock │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ 2. Resolve the plan and ask questions ││ • Dependencies, conflicts, providers, sizes │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ 3. Acquire and verify package archives ││ • Cache acquisition, checksums, sealed signatures │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ 4. Preflight the filesystem, run pre-transaction hooks ││ • Conflicts, backups, disk space, then pre hooks │└──────────────────────────────┬──────────────────────────────┘ │┌──────────────────────────────▼──────────────────────────────┐│ 5. Commit payload and records, then finish ││ • Removals, additions, ldconfig, post hooks │└─────────────────────────────────────────────────────────────┘The plan is reviewed before anything runs: dependency resolution, provider questions and the full list of additions and removals are settled while you are still being prompted, and the commit step only executes the reviewed plan.
There is no full filesystem rollback. If a mutation fails, RLPM stops at that step and reports completed and remaining work. An interrupted record-publication journal can require explicit recovery before RLPM will read the database again. Journal recovery restores coherent records; it does not undo payload changes or scriptlet effects. See execution and recovery for the distinction.
Version comparison targets libalpm’s C-locale ordering and is checked against fixed expectations
recorded from a pinned reference build. Repository priority and other resolution policy also
affect upgrade and downgrade selection. See version comparison
and dependency resolution.
Engine selection is also a build-time choice for packagers and embedders:
The CLI, the TUI and Shelly.PackageManager all accept the same build option. The default build
contains both engines and starts on libalpm; -Dlibalpm=false produces an RLPM-only build:
(cd Shelly.Cli.Zig && zig build -Dlibalpm=false)RLPM-only source packages omit the pacman build and runtime dependency that the default
variant carries. To choose distribution path defaults at build time, specify -Dpath-profile=pacman
(the default) or -Dpath-profile=devario.
Configurable upstream PKGBUILD recipes honor SHELLY_LIBALPM. Setting it to false builds the RLPM-only
variant; omitting the variable builds both engines:
SHELLY_LIBALPM=false makepkgRLPM-only recipes omit pacman and libalpm dependencies and verify that the resulting
binary contains no dynamic libalpm linkage. The dedicated packaging/arch/shelly-git
and Devario recipes select RLPM explicitly rather than inheriting that dual-backend default.
Download and action workers are reserved internal modes of the same shelly executable
(--internal-download-worker and --internal-rlpm-action-worker), re-executing /proc/self/exe
so there are no companion binaries to ship.
Applications embedding Shelly_Rlpm or Shelly.PackageManager must dispatch worker arguments
before application setup:
if (rlpm.Workers.dispatch(init, args[1..])) |status| std.process.exit(status);Alternatively, configure worker_executable (or OwnerConfiguration.worker_executable) with an
absolute path to an executable implementing both modes.
Per-command config (--config): Select another native configuration file (for example,
--config /etc/shelly.conf), before or after the command. The path is made absolute and retained
across privilege elevation and child processes.
Hook directory policy (HookDirMode): In pacman.conf or shelly.conf, setting
HookDirMode = Replace tells the backend to use only explicit HookDir entries instead of
appending them to system defaults (HookDirMode = Append).
Distribution path profiles (-Dpath-profile): Build-time path selection is independent of
backend selection. Builds default to the pacman profile. Independent distributions that do not
ship pacman select the devario profile:
pacman profile (default): /etc/pacman.conf, /etc/pacman.d/, /var/lib/pacman/,
/var/cache/pacman/pkg/, /etc/pacman.d/gnupg/, /usr/share/pacman/keyrings/, and
/usr/share/libalpm/hooks/.devario profile (pacman-less): /etc/shelly.conf, /etc/shelly.d/, /var/lib/shelly/,
/var/cache/shelly/pkg/, /etc/shelly.d/gnupg/, /usr/share/shelly/keyrings/, and
/usr/share/rlpm/hooks/./etc/shelly.conf uses the exact same INI format and directive syntax as pacman.conf
([options], SigLevel, repository sections, and mirror URLs).
libalpm is the initial default in dual-backend builds; RLPM-only builds default to RLPM.
Compatibility is tracked in an in-repository ledger, and complete libalpm parity remains
unfinished. Focused reference, GPG, namespace, and interoperability tests cover particular
contracts; they do not certify every production workflow or performance case.
Changing the backend affects subsequent operations only. It neither undoes a partial transaction nor recovers an interrupted journal, and it cannot select an engine omitted from the binary. Neither engine is selected automatically as a fallback after failure.
These guides explain the engine’s behavior and library contracts beyond the overview:
| Guide | What it covers |
|---|---|
| Databases and caches | Local records, tar and SQLite repositories, query policy, reloads, and reference lifetimes. |
| Version comparison | Epochs, releases, permissive metadata, ordering, and comparison limits. |
| Dependency resolution | Repository priority, providers, conflicts, removal, upgrades, and reviewable plans. |
| Transactions and locks | Transaction states, shared locking, stale-state checks, questions, and cancellation. |
| Integrity and signatures | Signing policy, checksums, key trust, consented import, and sealed archive bytes. |
| Downloads and refresh | Verified caches, concurrency, mirror retries, publication, and worker privileges. |
| Filesystem preflight | Archive validation, file ownership, conflicts, backups, path confinement, and space. |
| Hooks and scriptlets | Discovery, matching, action order, network controls, and failure outcomes. |
| Execution and recovery | Payload writes, durability barriers, local-record journals, and partial failures. |
NativePackageBackend.PKGBUILD recipes into package archives.