Shelly Changelog
Version v3.1.7 Latest
Shelly 3.1.7 patch notes
Shelly 3.1.7 introduces RLPM, Shelly’s native Zig package-management engine, alongside the existing libalpm backend. RLPM now covers the complete native package workflow: reading repositories, resolving dependencies, verifying and downloading archives, checking filesystem changes, running hooks and scriptlets, installing payloads, and updating the installed-package database.
This release also expands isolated builds, adds pinned build-environment plans, introduces split packaging, improves PKGBUILD previews and Flatpak permission displays, and fixes AppImage installation and native builder issues.
Comparison scope: changes since v3.1.6 through 833e1964, plus the prepared 3.1.7 version and packaging updates. The 3.1.7 release tag has not yet been created in this checkout.
Changes at a glance
| Area | Change from 3.1.6 |
|---|---|
| Native package engine | Adds an independent RLPM implementation and a shared interface for selecting RLPM or libalpm. |
| Build variants | Adds binaries that omit libalpm entirely, with RLPM as their default engine. |
| Distribution integration | Adds configurable Arch and Devario path profiles, explicit native configuration selection, and hook-directory policy. |
| Isolated builds | Adds AUR installation through fresh build roots, complete dependency plans, and RLPM provisioning. |
| Package output | Adds compression presets and a separate output architecture setting. |
| Packaging | Adds CLI, Flatpak backend, notification tray, and no-tray split packages. |
| User interface | Improves accessibility, Atoll PKGBUILD previews, permission explanations, and AppImage integration. |
| Cache cleanup | Expands --aur-cache to clear the contents of Shelly’s entire AUR cache. |
RLPM in detail
An independent engine for native packages
In 3.1.6, Shelly’s native package operations used libalpm. In 3.1.7, the package-manager interface can dispatch those operations to either libalpm or Shelly.Rlpm. RLPM implements its own database handling, resolver, transaction lifecycle, and executor; selecting it does not delegate the transaction back to libalpm.
The engine follows an owning Owner → Database → Package → Transaction model. The owner holds configuration, repository registrations, caches, callbacks, and the active transaction. Package references carry generation information so a reference from an invalidated database can be rejected. Prepared plans own their review data, allowing the selected package set, dependency relationships, answers, and warnings to remain stable while the operation proceeds.
The shared PackageManager layer gives the CLI and GTK application a common view of package records, progress, questions, errors, and cancellation. GTK continues to perform native operations through the CLI, so the selected backend also applies to those operations.
RLPM’s core is written in Zig. It still uses libraries and tools for specific jobs, including libarchive, SQLite, the shared HTTP/download stack, libcurl where needed, and GPG for signature verification. An RLPM-only build removes the libalpm dependency; it does not make every dependency disappear.
Backend selection and defaults
Default upstream builds include both engines and initially select libalpm. The selection is persistent and takes effect on the next CLI invocation:
shelly config get NativePackageBackendshelly config set NativePackageBackend rlpmOn a build that includes libalpm, select it again with:
shelly config set NativePackageBackend libalpmThe setting lives in Shelly’s user configuration, separately from the native repository configuration. An explicit saved selection survives changing build variants. An omitted setting uses the binary’s compiled default.
Build the CLI without libalpm with:
cd Shelly.Cli.Zigzig build -Dlibalpm=falseThis variant defaults to RLPM and omits libalpm imports, header translation, discovery, and linkage. Selecting libalpm in it produces BackendUnavailable. Invalid backend settings fail explicitly, and transaction failures do not trigger an automatic switch to another engine. Configuration commands remain available to correct the setting.
The dedicated packaging/arch/shelly-git and Devario recipes build RLPM-only variants. Their behavior therefore differs from the default dual-backend upstream build.
Existing package databases and repository formats
RLPM reads and writes the native version 9 local database format, including package descriptions, file inventories, backup hashes, installation reasons, validation history, and install/changelog/mtree members. It preserves CachyOS installed-repository provenance through the INSTALLED_DB field.
Repository support includes traditional tar databases and CachyOS repositories containing an embedded SQLite pacman.db. Both formats become the same internal package model. Tar ingestion uses libarchive’s supported compression filters; SQLite metadata is read in memory without extracting the database member into the installation root.
Database queries include exact lookup, groups, searches, file ownership data, reverse dependencies, and optional-dependency relationships. Repository usage settings distinguish synchronization, search, installation, and upgrade eligibility. Local descriptions and file lists load lazily rather than all being required for the initial identity scan.
Reloads build a replacement cache before publishing it. A malformed or rejected replacement retains the previous usable generation. Successful reloads invalidate old package references. This lets callers distinguish a failed refresh from an empty repository and prevents partially loaded indexes from becoming visible.
RLPM targets native database interoperability. Dedicated tests alternate RLPM and a pinned libalpm implementation against disposable roots, checking records, upgrades, downgrades, removals, and backup outcomes. That coverage is narrower than a claim of complete libalpm equivalence.
Version ordering and dependency resolution
RLPM adds native comparison of epochs, package versions, and releases, including permissive version strings found in package metadata. Numeric runs are compared without converting them to bounded integers. Package release is compared when both values contain it, following the reference behavior. Strict metadata construction remains separate from permissive comparison.
The resolver prepares installation, removal, and system-upgrade plans. It handles named and repository-qualified targets, package archives, versioned dependencies, virtual providers, conflicts, replacements, ignored packages, and assumed installed provisions.
Selection respects repository priority. A newer version in a lower-priority repository does not automatically override the preferred repository. Literal package candidates take precedence over provider selection, and multiple providers can be presented as a frontend question. Plans retain the selected providers and dependency edges so the result can be inspected.
Before accepting a plan, RLPM checks the proposed final state: surviving installed packages, scheduled removals, replacements, and incoming versions. That catches dependencies broken by the operation while avoiding rejection solely because an unrelated installed package already has a broken dependency.
Removal planning supports cascading removals, recursive dependency cleanup, inclusion of explicitly installed dependencies when requested, and unneeded filtering. Optional dependencies generate warnings rather than becoming mandatory removal blockers. Upgrade planning honors ignore rules, considers replacements, preserves packages absent from the repositories, and carries forward installation reasons.
Plans include ordered additions and removals, download and installed-size information, questions, warnings, and structured failures such as missing requirements or conflicting packages. A read-only resolution plan is review data; an executable transaction additionally requires a live lock and validation of the database state.
Transaction lifecycle and shared locking
A normal RLPM transaction follows this sequence:
- Acquire the configured database’s
db.lckand load current state. - Resolve targets and prepare a stable plan.
- Acquire and verify the required archives.
- Check the proposed filesystem and database changes.
- Run applicable pre-transaction hooks.
- Process removals and additions, including package scriptlets and local-record publication.
- Perform linker-cache maintenance and applicable post-transaction hooks.
- Release transaction resources and the owned lock.
RLPM and libalpm use the same database lock, allowing cooperating writers to exclude each other. RLPM retains the lock descriptor, checks its identity before removal, and refuses to delete a replacement lock belonging to another operation. Ordinary initialization does not silently remove a stale or foreign lock. Commit is rejected when the transaction lacks its required lock, including under NOLOCK.
The engine fingerprints local and sync state around preparation and before commit. Out-of-band database changes produce StaleDatabaseState instead of silently executing a different package set. Configuration and repository mutations are frozen while the transaction is active.
Typed states distinguish preparation, execution, completion, failure, and interruption. Callback reentry is rejected. Cancellation is checked during resolution, transfers, preflight, actions, and payload work, and deferred frontend questions are connected to the same cancellation path.
Lock errors now report the actual configured database path before the operation completes, including custom paths containing spaces or quotes.
Integrity checks and signing policy
RLPM applies effective package and database signature policy, including inherited repository policy and the distinction between local and remote archive sources. Required signatures must be present. Optional policy permits an absent signature but still requires a present signature to satisfy validity and trust requirements.
Signature handling uses the configured package keyring and its trust database. Unknown-key import requires a frontend decision. A successful import triggers verification again and does not grant trust by itself. Structured results retain signing fingerprints, trust and validity information, and GPG diagnostics.
Repository digest checks prefer SHA-256 and can fall back to MD5. Embedded and detached signatures follow their respective reference policy rules. Disabling signature verification does not disable supplied digest checks.
Verified input is copied into a sealed Linux memory-backed file. Verification, archive parsing, and subsequent extraction read the retained bytes, so replacing the original pathname after verification cannot substitute another archive. This requires memfd sealing and /proc, and consumes RAM or swap proportional to the retained archives.
The API distinguishes metadata inspection from authenticated loading: Package.loadArchive parses metadata without claiming verification, while Owner.loadPackage applies policy and retains verified bytes. Seeing a checksum or signature advertised in repository metadata is not represented as having already checked the package archive.
Downloads and repository refresh
RLPM uses the shared Shelly.Download transport for package acquisition and database refresh. It searches configured caches, verifies cache hits under current policy, supports resumable transfers, handles mirror retries, and keeps payload/signature acquisition within the bounded download queue.
ParallelDownloads governs package and repository transfers, with a maximum worker count of 255. Independent repository payload/signature pairs can download concurrently. Verification, key questions, parsing, and publication remain on the owning thread.
Download progress now distinguishes bytes transferred from final acceptance. A completed transfer can still be undergoing integrity checks or publication, and a failed candidate can move to another mirror. CLI and isolated-build progress show these stages without treating a finished transfer bar as a successful transaction.
Refresh reports updated, unchanged, skipped, and failed outcomes separately for each repository. Candidates are verified and parsed before publication. Invalid downloads retain the previous usable database. Journals and directory locks protect publication of a database and its detached signature for cooperating RLPM readers, with recovery for interrupted publication.
When privileged downloads use a configured sandbox user, worker processes can drop credentials and apply Landlock filesystem restrictions and seccomp syscall restrictions. Setup failure aborts that request. The parent retains its own credentials and verifies worker output before publication. These protections depend on the configured switches and kernel facilities.
Download-only transactions with additions acquire verified archives without installing package payloads or running package actions.
Filesystem preflight and configuration files
Before extraction, RLPM traverses the archives and constructs a manifest of the intended effects. It checks archive identity and dependency metadata against the plan, inventories payload paths, and detects both package-to-package and package-to-filesystem conflicts.
Checks account for existing owners, shared directories, scheduled removals, and ownership transfers during upgrades. A permissive overwrite pattern does not authorize replacing an unowned directory tree. Missing installed file records fail preflight instead of making ownership disappear.
The manifest covers backup handling, NoUpgrade, NoExtract, overwrite rules, .pacnew, and .pacsave. Backup decisions compare the previous package hash, current local content, and incoming content. The executor recomputes relevant decisions after hooks and scriptlets, since those actions may change the files being considered.
Archive paths are confined to the installation root with openat2. Absolute archive entry names, traversal components, invalid hardlinks, duplicate payload paths, and inconsistent inventories are rejected. The implementation does not fall back to unconstrained path resolution when the required kernel support is unavailable.
Preflight also checks mount access and available space. Estimates include temporary extraction, directories, database records, and publication staging. They are deliberately more conservative than a payload-only estimate and can reject work on a nearly full filesystem that the reference implementation would accept.
Hooks and package scriptlets
RLPM discovers and evaluates native package hooks, including package and path triggers, operation matching, dependencies, ordering, NeedsTargets, AbortOnFail, and CachyOS NetworkAccess. Later hook directories can override earlier definitions; empty files and /dev/null masks disable lower-priority hooks of the same name.
Package installation, upgrade, downgrade, reinstall, and removal run the corresponding scriptlet stages. Incoming scripts come from retained archive data, and post-installation stages use the newly installed local record. Version arguments are quoted literally before being passed to shell functions.
Actions run in a fresh worker process rooted in the target filesystem. Parent working directory, credentials, and environment remain separate. Output is streamed back to the operation, and cancellation terminates the action process group.
CachyOS-style network isolation applies to hooks and scriptlets by default, with explicit controls for permitting access. Download filesystem/syscall sandbox controls and action network controls remain distinct.
Fatal pre-hook conditions prevent package mutation. Failures treated as nonfatal by the native behavior, such as ordinary scriptlet or post-hook failures, are retained as warnings and action outcomes. Failed or interrupted payload execution does not run successful-completion post hooks. Isolated provisioning additionally treats package setup failures as a failed provisioning operation.
Payload execution and database recovery
RLPM installs payloads through held directory descriptors and private staging, then publishes entries with descriptor-relative operations. It preserves supported file modes, ownership, timestamps, sparse extents, extended attributes, and file capabilities. Its extraction flags follow the pinned native behavior, which does not enable ACL extraction. Removal preserves nonempty directories rather than recursively deleting their contents.
Payload writeback is batched at package boundaries. Changed filesystems are flushed with syncfs() before a new package record is published. The CLI can report Finishing writes for <package> while that barrier runs. A flush failure stops the operation and prevents publication of the current package’s new record.
Local records are staged, synchronized, and published using a durable journal. Interrupted record publication causes DatabaseRecoveryRequired. The library’s Owner.recoverLocalDatabase API acquires the normal writer lock and restores a coherent record state; it does not remove a foreign or stale writer lock automatically.
Record recovery is not full package rollback. Payload changes, scriptlet effects, and previously completed packages can remain after failure or cancellation. Execution reports retain the current boundary, affected path, completed and remaining packages, publication status, and underlying errors. RLPM stops at a failed mutation instead of continuing to report the package as successfully extracted.
One executable for worker operations
Download and action workers are private modes of the hosting executable. Shelly re-executes /proc/self/exe, including when an upgrade has replaced the installed pathname. Deployments no longer need separate worker executables or paths into a build cache.
Library embedders must dispatch worker modes before normal application initialization or provide an explicit worker executable implementing the dispatcher. A dual-backend host still carries its compiled libalpm dynamic dependency into workers; an RLPM-only host excludes it.
Compatibility status
RLPM is integrated and can execute package transactions, but complete libalpm compatibility remains unfinished. The compatibility ledger continues to track missing, partial, and representation-only coverage. It does not certify full parity across the public API, malformed inputs, all repository configurations, or every production workflow.
The repository adds independent reference fixtures and focused tests for version ordering, database formats, signature policy, dependency resolution, locking, downloads, preflight, hooks, execution, and interoperability. Privileged namespace, GPG, and pinned-binary tests have additional environment requirements. Historical test results in the component documentation are not a fresh validation of every 3.1.7 build.
Intentional differences include stricter archive validation, conservative disk-space estimates, explicit stale-state rejection, safer lock cleanup, sealed archive ownership, and retained partial-failure diagnostics. Large-database fingerprint costs and wider production acceptance remain relevant limitations; this release does not establish a universal performance advantage over libalpm.
See the native backend guide, RLPM overview, and compatibility ledger for the implementation contracts and evidence.
Arch and Devario integration
Backend selection and distribution paths are independent. An RLPM-only build can use Arch’s existing paths, while the Devario profile supplies Shelly-owned locations:
| Resource | Arch profile | Devario profile |
|---|---|---|
| Native configuration | /etc/pacman.conf |
/etc/shelly.conf |
| Package database | /var/lib/pacman |
/var/lib/shelly |
| Package cache | /var/cache/pacman/pkg |
/var/cache/shelly/pkg |
| Keyring | /etc/pacman.d/gnupg |
/etc/shelly.d/gnupg |
| Public key bundles | /usr/share/pacman/keyrings |
/usr/share/shelly/keyrings |
| System hooks | /usr/share/libalpm/hooks |
/usr/share/rlpm/hooks |
| Administrator hooks | /etc/pacman.d/hooks |
/etc/shelly.d/hooks |
Changing profiles supplies different defaults; it does not move or convert an existing database, cache, or keyring. Runtime selection of RLPM alone does not change the profile.
The global --config option selects a native configuration file for one invocation. The selection is preserved through elevation, AUR coordinators, and bootstrap operations. Explicitly unreadable configuration files or includes fail rather than silently using defaults.
Hook configuration adds HookDirMode = Append|Replace. Append remains the default. Replace uses only the listed directories, and an empty replacement list disables discovery. Both backends receive the resolved ordered list.
Devario keyring population uses the profile’s public bundle directory, with shelly-key --populate-from available to select another source. The new devario-devel metapackage supplies native and isolated build tools without making pacman or archlinux-keyring part of that metapackage.
Isolated builds and pinned dependencies
AUR packages can now be built in a fresh root before installation:
shelly -Ia --isolated <package>Each package base gets its own root. Repository build dependencies stay in the guest; exported archives and their runtime dependencies are installed through the normal host transaction. The workflow supports --needed, split-package selection, and exact-commit --version installation.
Isolated provisioning uses the selected native backend. RLPM-only binaries provision an explicit userspace and build-tool set instead of requiring the usual base and base-devel baseline. A recipe can still declare pacman or libalpm as build dependencies when it needs them; an RLPM-only coordinator does not prohibit building software that uses libalpm.
The builder adds --resolve-dependencies and --dependency-plan for isolated environments. Resolution produces a versioned JSON plan containing the complete bootstrap and recipe package set, versions, repository locations, SHA-256 metadata, dependency relationships, and digests tying the plan to the reviewed inputs and configuration. Provisioning checks the selected versions and hashes against the plan before installation.
Missing repository dependencies and missing archive SHA-256 metadata produce distinct diagnostics. Incomplete plans stop provisioning, with unresolved requirements reported in stderr, logs, and JSON errors. Repository resolution does not assume a missing package can be obtained from the AUR.
Host configuration forwarding is corrected: review and provisioning use the selected host configuration, while the guest receives its generated local configuration instead of a host-only pathname.
Isolation still requires the relevant namespace and systemd-nspawn facilities. AUR-only build dependencies and signing with private keys inside the guest remain unsupported. --isolated cannot be combined with --chroot or dependency-only installation modes. See isolated builds.
Native builder improvements
- Dynamic versions: valid changes from
pkgver()update the PKGBUILD, resetpkgrelto1, and refresh version-dependent metadata before building. Isolated builds validate the guest’s version/release edit before applying it to the original host file as the invoking user; concurrent changes prevent writeback. - SRCINFO generation:
--makesrcinfoprepares sources and evaluatespkgver()when present, rather than retaining stale VCS metadata. - Large split packages: evaluated function definitions are carried into lifecycle execution through a private script, avoiding Linux’s per-argument size limit. Dynamically generated split-package functions remain available to the builder.
- Source extraction: ordered archive overlays support replacing earlier regular entries while preserving source aliases, Git checkout trees, hardlink rules, and conflicting-type checks. This addresses source layouts used by packages such as VMware and Rust-related builds.
- Source cache:
destinations.sourcesis consistently exported asSRCDESTduring metadata evaluation and lifecycle steps, including sandboxed builds. - Compression:
--compression-level 1..5andpackage.compression_levelprovide conservative through maximum-effort presets for Zstandard, gzip, xz, and bzip2. Omission retains library defaults; preset 3 is not a forced new default. - Output architecture:
package.carchchanges the architecture written into package metadata and filenames while preservingbuild.carchfor PKGBUILD evaluation. Packages declaringanyremainany. The setting also reaches isolated builds. - Source verification and parsing: fixes improve source-key handling, GPG forwarding, URL escaping, shell array expansion, and recognition of braces in shell command position.
See build configuration for compression mappings and output architecture settings.
Split packaging
New split recipes separate the application into shelly, shelly-cli, shelly-flatpak-backend, and shelly-notify, with matching -git variants where applicable. shelly-notify-none and its Git variant satisfy the tray dependency for users who want to omit the notification service.
The CLI package owns the command-line executables, completions, manual, and privileged-operation policy. The Flatpak implementation is packaged separately. The existing optional Flatpak backend architecture predates this release; 3.1.7 expands its packaging rather than introducing Flatpak support for the first time.
Arch and Devario recipes supply their respective path profiles, and their versioned dependency/provision metadata is updated for 3.1.7. Git recipes continue to follow the development branch and calculate their build version from Git history.
Interface and desktop changes
PKGBUILD review
The GTK PKGBUILD preview integrates Atoll-backed preview data, scan findings, and source-file information, including a retry path for scans. The CLI exposes the same scan flow through search aur --pkgbuild --scan-pkgbuild when the Atoll mirror is enabled, with text and JSON output. Scan findings supplement review; they are not a guarantee that a build is safe.
Standard search results gain links for AUR packages, and multi-selection gains additional context.
Flatpak permission explanations
CLI and GTK permission views group raw tokens into readable concerns such as network access, devices, files, and session services. Related entries are deduplicated and ordered by concern level. Filesystem access modes, denied permissions, and conditional tokens retain their meaning.
The backend reads the relevant metadata sections correctly. Unreadable or malformed permission data is no longer presented as if the application requested no permissions. Permission-dialog cleanup also releases copied rows correctly.
Accessibility and appearance
GTK controls gain accessible names and roles. Keyboard focus is restored after lockouts, navigation targets remain visible, first-run page changes are announced, and transaction progress and empty search results receive screen-reader feedback. New accessibility checks inspect populated UI structure and Orca announcements.
The Shelly icon setting now affects icon fetching and package views when changed. Translation work includes Polish, German, Italian, Brazilian Portuguese, and European Portuguese, alongside refreshed translation catalogs.
AppImage fixes
AppImages gain GTK installation and deep-link/file-association integration. Metadata synchronization handles relocation more carefully, updates desktop launch paths, preserves custom arguments and environment settings, and retains the prior integration when relocation fails.
Copying and rollback preserve executable permissions. This fixes cases where an installed or restored AppImage became non-executable and desktop menus hid its launcher because TryExec no longer pointed to an executable file.
Automatic file-size units
Enable automatic units in human-readable CLI output with:
shelly config set FileSizeDisplay AutoAuto chooses B, KiB, MiB, GiB, or TiB and preserves negative size changes. Existing fixed-unit modes remain available, Megabytes remains the default, and structured output continues to use numeric byte counts.
Cleanup and other fixes
--aur-cache now deletes all contents of the invoking user’s Shelly cache, including checkouts, sources, build trees, archives, and metadata, including caches for packages no longer installed. Previously it targeted built archives and their signatures.
The command previews entries and asks for confirmation. It retains the cache root, removes symlinks without following their targets, and excludes output destinations outside Shelly’s cache. The GTK Clean Package Cache action also clears this entire cache; the repository retention count does not limit AUR cache cleanup.
shelly purify standard --cache --aur-cache --dry-runAdditional fixes make libalpm database/signature downloads advance together to the next mirror after a signature download failure, improve isolated dependency-error reporting, and make RLPM bootstrap stages and download processing more visible during long operations.
Upgrade considerations
- Check the installed variant before choosing a backend: upstream dual-backend builds retain libalpm as the initial default, while the dedicated RLPM-only recipes cannot select libalpm.
- Keep backend choice separate from path configuration. Selecting RLPM with the Arch profile continues to use the configured Arch database; selecting a Devario build does not migrate that database automatically.
- Preserve the intended signature policy and populate the keyring selected by the profile or configuration. Removing libalpm does not remove the need for package trust configuration.
- Treat interrupted native transactions as potentially partial. RLPM’s record journal helps recover database consistency, but it does not reverse every payload or scriptlet effect.
- Review the expanded
--aur-cachescope before using it when cached source trees or build results matter. - Ensure consumers accept any architecture chosen through
package.carch; it changes package labeling, not the compiler target or the PKGBUILD’s build architecture.
