github Seafoam-Labs/Shelly-ALPM v3.1.0

5 hours ago

Shelly-ALPM v3.1.0 — Building Arch Packages, the Shelly Way

Shelly v3.1 is here, and its headline feature is something we have wanted since before the Zig rewrite began: Shelly can now build Arch Linux packages itself.

Until now, Shelly handled AUR discovery, dependency resolution, package review, and installation while handing the actual PKGBUILD execution to makepkg. In v3.1, that final handoff is gone from the default AUR workflow. Shelly now owns the complete build pipeline, from reviewing a PKGBUILD to publishing a signed, pacman-compatible package archive.

This is not a wrapper around makepkg. The new builder is part of Shelly’s native package-management library and can be used directly through the new shelly build command.

🏗️ Meet shelly build

Point shelly build at a PKGBUILD and Shelly will turn it into an installable Arch package:

# Build ./PKGBUILD
shelly build

# Build a PKGBUILD somewhere else
shelly build /path/to/PKGBUILD

# Install missing dependencies and then build
shelly build --sync-deps /path/to/PKGBUILD

Shelly follows the familiar PKGBUILD lifecycle while managing the entire process internally:

  1. Parse the PKGBUILD without immediately executing its top-level shell code.
  2. Display the PKGBUILD, related files, and security findings for review.
  3. Lock the approved contents with an integrity digest.
  4. Safely evaluate dynamic metadata and re-review any newly discovered files.
  5. Download and verify sources.
  6. Run verify(), prepare(), pkgver(), build(), and check() when present.
  7. Run package() or the appropriate split-package function.
  8. Generate package metadata, assemble the archive, and optionally sign it.
  9. Publish the finished artifacts and clean temporary work directories.

The result is still a normal Arch package. Shelly writes makepkg-compatible .PKGINFO, .BUILDINFO, .MTREE, .INSTALL, and .CHANGELOG entries and produces archives that pacman and other Arch tools understand.

📦 Full PKGBUILD support

The builder is designed around Arch’s existing PKGBUILD format rather than introducing a Shelly-specific recipe format.

It supports:

  • Standard verify(), prepare(), pkgver(), build(), check(), and package() functions.
  • Single packages and split packages, including package-specific metadata overrides.
  • Dynamic package names and package arrays resolved by top-level Bash logic.
  • Architecture-specific sources, checksums, dependencies, and metadata.
  • The usual $startdir, $srcdir, $pkgdir, $CARCH, and $CHOST build variables.
  • PKGBUILD helper functions and makepkg-style msg, msg2, plain, warning, and error output helpers.
  • Local files, HTTP and HTTPS downloads, file:// sources, and Git repositories.
  • Renamed sources using the name::url syntax.
  • Git branches, tags, commits, and signed Git objects.
  • noextract=() handling and automatic extraction of supported archives.
  • MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, and BLAKE2 checksums.
  • Detached .sig, .sign, and .asc signatures, including compressed signatures.
  • validpgpkeys=() fingerprint enforcement.
  • Dynamic pkgver() results and package metadata changed inside package() functions.
  • Package architecture validation and correct any package output.
  • Split-package selection using the advanced, repeatable --package <name> option.
  • Configurable build flags, LTO flags, make flags, ccache, and distcc.
  • Detached signing of completed package archives.

Shelly also provides virtual root-ownership handling during package(). Common commands such as chown root, chgrp root, and install -o root -g root work without changing ownership on the host. The archive writer records the correct root ownership in the package itself. Device-node creation and unsupported privileged metadata operations are rejected.

🛡️ Beyond makepkg and improving trust

makepkg is the official Arch package-building tool. Shelly’s builder keeps the parts package maintainers expect while adding protections and package-manager integration that makepkg does not provide on its own.

Review before execution

Shelly does not begin by blindly sourcing the PKGBUILD. It parses the file first and presents it for review before allowing package-controlled code to run.

The review includes:

  • The complete PKGBUILD.
  • Local source files.
  • Install scripts and changelogs.
  • Binary-file warnings.
  • Suspicious post-install commands.
  • Homograph and lookalike-character warnings.
  • Unsafe local-source references.
  • Top-level command substitutions that will execute during the build.

If dynamic PKGBUILD evaluation discovers additional sources, install scripts, or split-package members, Shelly stops and asks for a supplemental review.

Review integrity protection

Approving a file is not enough if that file can be changed before it executes. Shelly hashes the PKGBUILD and every related reviewed file, then checks those contents again immediately before execution.

The same digest is carried across privilege elevation when --sync-deps is used. If the PKGBUILD, install script, changelog, or local source changes after approval, the build is rejected.

Packaging also uses the exact reviewed bytes for install scripts and changelogs instead of reopening those files later.

Optional Landlock confinement

Shelly can place every untrusted PKGBUILD lifecycle step inside a Linux Landlock filesystem sandbox.

When enabled, the build functions can access the build directory and normal system toolchain paths, but they cannot freely browse or modify the user’s home directory. Extra read-only or writable paths can be granted for tool caches such as Cargo, Gradle, npm, or ccache.

The sandbox applies to:

  • Dynamic PKGBUILD evaluation
  • verify()
  • prepare()
  • pkgver()
  • build()
  • check()
  • package() and split-package functions

Source downloads, package assembly, logging, and GPG signing stay outside the sandbox, so the user’s GPG keyring never needs to be exposed to package-controlled code.

Landlock is opt-in. When enabled on a system without Landlock support, Shelly fails before executing the first build step instead of silently running the build without protection.

AUR-aware dependency installation

--sync-deps resolves dependencies through Shelly’s package manager rather than simply passing them to pacman.

That means it can:

  • Detect dependencies already satisfied by installed packages or provides=().
  • Install missing repository dependencies.
  • Locate and build dependencies that are only available from the AUR.
  • Resolve dependencies for every requested split-package member.
  • Include checkdepends only when tests are enabled.
  • Keep runtime dependencies installed.
  • Remove newly installed build-only and check-only dependencies afterward.
  • Perform that cleanup after both successful and failed builds.

By comparison, makepkg’s documented --syncdeps delegates missing dependencies to pacman, while --rmdeps removes them only following a successful build. It does not independently build missing AUR dependencies. See the official makepkg documentation.

The elevated Shelly process only coordinates dependency transactions. The PKGBUILD itself is always executed again as the original non-root user, with NO_NEW_PRIVS applied to the builder and inherited by its children.

Guided PGP key handling

When a PKGBUILD pins source-signing keys through validpgpkeys=(), Shelly checks the invoking user’s keyring before downloading and building.

If a required key is missing, Shelly shows the complete fingerprint and asks whether it should be imported using shelly keyring recv --user. After import, the key is checked again before the build continues.

Detached signatures and signed Git objects must match the pinned primary fingerprint. Bad, revoked, missing, or unexpected keys fail the build.

Safer source handling

Shelly’s source pipeline adds several defensive boundaries:

  • Every non-VCS source must have integrity checks.
  • Cached downloads are written to temporary files and atomically committed.
  • A cached HTTP source that fails its checksum is discarded, downloaded again, and rechecked.
  • Git sources use reusable mirrors that are refreshed before local materialization.
  • All sources are acquired and verified before any archive is extracted.
  • Archive extraction rejects absolute paths, directory traversal, unsafe symlink destinations, and oversized entries.
  • Source trees are assembled in staging directories and only moved into place after preparation succeeds.

Atomic package publication

Completed archives are written under randomized temporary names. Shelly publishes them with an atomic rename only after archive creation and optional signing succeed.

If any member of a split-package build fails, already published artifacts from that build are removed. Signatures are rolled back with their corresponding packages, avoiding partial split-package results and orphaned .sig files.

Structured progress and mandatory logs

Every build is a structured Shelly operation. Output can be streamed into the normal CLI or the GTK transaction interface, with phase changes, package names, errors, progress percentages, cancellation, review questions, and completed artifact paths preserved as distinct events.

Every build also receives a log before source processing begins. Logs:

  • Record phase boundaries.
  • Label stdout and stderr separately.
  • End with success, failed, or cancelled.
  • Are retained for every outcome.
  • Fail the build if Shelly cannot create or continue writing the log.

Logging in makepkg is optional through --log; Shelly makes the audit trail part of the build contract. See makepkg(8).

🎛️ shelly build options

  • --reviewed, -r — skips the interactive review prompt when the caller has already reviewed the package. Integrity hashing and change detection remain active.
  • --sync-deps, -s — installs missing repository and AUR dependencies, runs the build as the invoking user, and removes build-only dependencies afterward.
  • --check, -c — runs check() and includes checkdepends.
  • --no-check — skips check() and does not install checkdepends.
  • --sign — creates a detached OpenPGP signature beside every package archive.
  • --nosign — disables signing even when it is enabled in configuration.
  • --key <fingerprint> — selects the GPG key used to sign the finished package.
  • --noverify — skips the PKGBUILD’s custom verify() function. It does not disable built-in checksum or source-signature verification.
  • --package <name> — builds only the selected split-package member. It may be repeated to select several members.
  • --isolated, -i — reserved for the future isolated-root builder and currently nonfunctional.

The usual Shelly global options, including noninteractive and UI operation modes, continue to apply.

⚙️ Introducing shellybuild.conf

The new builder has its own configuration file, shellybuild.conf. It replaces makepkg.conf for Shelly’s in-process builder only.

Shelly merges:

  1. /etc/shellybuild.conf
  2. $XDG_CONFIG_HOME/shelly/shellybuild.conf
  3. ~/.config/shelly/shellybuild.conf when XDG_CONFIG_HOME is unavailable

The system file installed by Shelly is a commented template, so upgrading does not silently replace the builder’s compiled defaults. It is also registered as a pacman backup file so local administrator changes are preserved.

Configuration covers:

  • Target architecture and host triplet.
  • C, C++, preprocessor, linker, LTO, and make flags.
  • Default check() behavior.
  • ccache and distcc.
  • Packager identity and package archive format.
  • Package options and strip flags.
  • Signing defaults and signing key.
  • Separate build, package, source-cache, and log destinations.
  • Landlock enablement and additional read or write paths.

Unlike makepkg.conf, which is sourced as shell code, shellybuild.conf is data-only TOML. Unknown keys, unsupported options, malformed values, unsafe extensions, and relative destination paths fail before the PKGBUILD runs. See the official description of sourced makepkg configuration in makepkg.conf(5).

PKGBUILD options=() entries still override configured package options using the familiar option and !option form.

🐚 A better AUR workflow everywhere

The standalone command and Shelly’s regular AUR installs use the same builder. Improvements made to shelly build therefore also apply when installing or upgrading AUR packages from the CLI or GTK application.

This release also improves compatibility with real-world PKGBUILDs:

  • Added dynamic scalar and indexed-array evaluation.
  • Fixed dynamically generated split-package members.
  • Improved architecture-specific metadata and package selection.
  • Added support for top-level Bash expansion and source command substitution.
  • Fixed local source names containing spaces.
  • Improved Linux kernel and NVIDIA DKMS package builds.
  • Added source-signing key support needed by packages such as Spotify.
  • Improved handling for source-less packages, bare Git sources, package metadata overrides, and makepkg message functions.
  • Made PKGBUILD review contents selectable and copyable in the GTK interface.
  • Improved failure reporting so the failing package and lifecycle stage are easier to identify.

✨ More v3.1 improvements

Beyond the builder, v3.1 includes another substantial round of reliability and usability work:

  • Added run0 as a supported privilege-elevation backend.
  • Improved shell completion for bare actions and combined shortcodes.
  • Fixed terminal table wrapping and rendering artifacts.
  • Made optional-dependency prompts identify the package they belong to.
  • Improved transaction completion and failure output.
  • Allowed combined updates to continue when an optional backend is disabled or unavailable.
  • Improved ALPM errors, package cache recovery, hooks, and human-readable transaction logging.
  • Added gzip and deflate HTTP response support and fixed TLS initialization and stalled response-body timeouts.
  • Improved AppImage update detection, static URL validation, symlink handling, metadata cleanup, icons, and update editing.
  • Removed the remaining C# AppImage database migration bridge.
  • Updated German, French, Hungarian, Polish, Russian, and other translations.

🔄 Upgrade notes

  • shelly build creates packages but does not install its standalone output. Shelly’s normal AUR install workflow handles both building and installation.
  • Landlock confinement is disabled by default and must be enabled in shellybuild.conf.
  • The sandbox restricts filesystem access, not networking. /tmp remains shared and /proc remains visible.
  • Clean or isolated root builds are still being developed. The current --isolated option must not be relied on.
  • The current source pipeline supports local files, file://, HTTP, HTTPS, and Git. Other makepkg VCS protocols and arbitrary DLAGENTS are not yet supported.
  • Source-package creation, SRCPKGDEST, repackaging, integrity generation, and arbitrary shell configuration are not currently provided by shelly build.
  • Shelly’s content-changing tidy phase currently implements binary and library stripping. Some additional makepkg package options are recognized for compatibility but are not yet fully modeled.
  • External makepkg and clean-chroot workflows do not read shellybuild.conf.

❤️ Thank you, contributors!

Shelly v3.1 represents months of work across the package builder, PKGBUILD parser, AUR manager, CLI, GTK interface, AppImage support, networking, translations, and transaction system.

A huge thank you to everyone who helped build and test this release:

Full Changelog: v3.0.6...v3.1.0

Release pull request: #1793

Don't miss a new Shelly-ALPM release

NewReleases is sending notifications on new releases.