shelly build
Compiles local recipes without installing.
Use this when you are writing a PKGBUILD, testing a modified recipe, or building a standalone package archive (.pkg.tar.zst) for distribution or later installation.
shelly build compiles a PKGBUILD recipe into an installable Arch Linux package archive (.pkg.tar.zst). It is
Shellyβs native, standalone package build engine, the same shelly install aur uses, made entirely in
Zig without relying on makepkg or fakeroot.
Shelly resolves recipe metadata with a static parser that never executes arbitrary shell code during analysis. Recipe lifecycle functions run strictly as ordinary Bash child processes of an unprivileged, non-root user, protected by interactive security reviews, cryptographic digest locks, and optional Linux kernel Landlock sandboxing.
shelly buildShelly offers two distinct workflows for building packages:
shelly build
Compiles local recipes without installing.
Use this when you are writing a PKGBUILD, testing a modified recipe, or building a standalone package archive (.pkg.tar.zst) for distribution or later installation.
shelly install aur
Fetches, reviews, builds, and installs in one command.
Use this when you want to discover, download, and install a package directly from the Arch User Repository (AUR) onto your current system.
makepkg| Feature | shelly build |
makepkg |
|---|---|---|
| Metadata Parsing | Static analysis (safe, bash-aware parser; no arbitrary code execution) | Sourced directly in host Bash |
| Privilege Model | Strict non-root builder execution | Requires fakeroot / LD_PRELOAD |
| File Ownership | Virtual ownership journal (mapped by inode into .PKGINFO & .MTREE) |
Relies on fakeroot host translation |
| Integrity Checks | SHA-256 review digest lock (prevents TOCTOU modifications) | Manual recipe inspection |
| Sandboxing | Kernel Landlock LSM (restricts filesystem access to $HOME) |
Unrestricted host access by default |
| Configuration | Structured TOML (shellybuild.conf) |
Shell script (makepkg.conf) |
Ensure your directory contains a valid PKGBUILD and any local source or install files:
cd ~/src/my-packageshelly buildTo automatically fetch and install missing build dependencies before compiling, pass -s (or --sync-deps):
shelly build -sBefore executing any shell commands, Shelly presents the full PKGBUILD, local source files, .install scriptlets, and results from its automated security scans (e.g. homograph detection, malicious scriptlets, or privilege elevation).
Confirm to proceed with the build, or decline to cancel safely.
Upon completion, the compressed package archive (e.g. my-package-1.0.0-1-x86_64.pkg.tar.zst) is placed in the packages destination configured in shellybuild.conf (falling back to the current directory).
Install it onto your system using Shellyβs standard installer:
shelly install standard ./my-package-1.0.0-1-x86_64.pkg.tar.zst-l (--install) installs the archives the build just produced, so a package no longer has to be built and then
installed by hand:
shelly build --install# Equivalent to makepkg -sishelly build -s --installshelly -AslLike makepkg -i, only the freshly built archives are added, so combine the flag with -s when the packageβs own
dependencies may be missing.
Administrator credentials are requested once, up front β the builder locks itself against elevation with
PR_SET_NO_NEW_PRIVS and can never elevate afterwards. The build runs unprivileged as your regular user, and the
elevated coordinator installs the archives afterwards, through the same path as shelly install standard <archive>.
Other details worth knowing:
-s -l, build-dependency cleanup runs after the install, so a runtime dependency the built package now needs
is not removed.-i, the guest exports the archives and the host coordinator installs them; the container never writes to the
host database.--json, --ui-mode, --review-only, or --makesrcinfo exits 2 with
Cannot combine --install with <mode>. before building.Security is at the core of Shellyβs build architecture. Before any code is executed:
sudo, su, run0), network calls in build functions (curl, wget),
and Unicode homograph spoofing..install scripts or local
patches) are displayed for your review.shelly build [<pkgbuild>] [options]| Option | Short | Description |
|---|---|---|
--sync-deps |
-s |
Automatically install missing build and runtime dependencies with before building. |
--check |
-c |
Execute the check() test suite in the PKGBUILD and install check dependencies. |
--no-check |
Skip the check() test function, overriding shellybuild.conf. |
|
--isolated |
-i |
Build in a fresh, unprivileged systemd-nspawn container environment. |
--install |
-l |
Install the built package archives after a successful build. With -s this mirrors makepkg -si. |
--sign |
Generate a detached OpenPGP signature (.sig) next to each built package archive. |
|
--nosign |
Skip package signing, overriding shellybuild.conf. |
|
--key <key> |
Specify the GPG key ID or 40-character fingerprint to use for package signing. | |
--package-destination <dir> |
Save package archives to a specified absolute directory instead of the default location. | |
--reviewed |
-r |
Mark the recipe as reviewed and bypass the interactive prompt (use only for automated workflows or trusted recipes). |
--makesrcinfo |
Statically parse the recipe, generate .SRCINFO to standard output, and exit without building. |
|
--noverify |
Skip the PKGBUILDβs verify() function (not recommended). |
Shelly provides concise shortcodes where -A represents shelly build. Options attach directly to the shortcode flag:
shelly -A # Build PKGBUILD in current directoryshelly -As # Build and install missing dependenciesshelly -Al # Build, then install the built packageshelly -Asl # Sync dependencies, build, and install (makepkg -si)shelly -Ac # Build and run test suites (check)shelly -Asc # Build, install dependencies, and run check()shelly -Ai # Build in an isolated systemd-nspawn containershelly -Ar # Build and mark recipe as reviewedshelly -Ars # Non-interactive build with dependency syncshelly -A ~/pkg/PKGBUILD # Build recipe at specific pathshelly -Ah # Show build command helpFor the complete options list, see the CLI Reference.
For power users, package maintainers, and curious developers, Shellyβs build engine operates across several dedicated stages:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ 1. Static Parsing & Security Scans ββ β’ Word expansion, variable map, dependency resolution ββ β’ Security checks (privilege, obfuscation, homographs) βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ 2. Review & Digest Lock ββ β’ Interactive confirmation of PKGBUILD + local files ββ β’ Compute SHA-256 review digest snapshot βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ 3. Source Pipeline ββ β’ Download HTTP(S) sources to cache & clone Git mirrors ββ β’ Verify checksums (sha256, b2, etc.) & PGP signatures ββ β’ Safe extraction (guards against path traversal & bombs)ββ β’ Execute verify() step βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ 4. Lifecycle Execution (Sandboxed Non-Root Bash) ββ β’ prepare() β pkgver() β build() β check() ββ β’ Landlock LSM restricts access to $HOME βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββ 5. Package Assembly & Virtual Ownership ββ β’ package() execution per split-package member ββ β’ Tidy/strip binaries & apply purge cleanups ββ β’ Generate .PKGINFO, .BUILDINFO, .MTREE metadata ββ β’ Assemble .pkg.tar.zst archive & optional GPG signing ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββTraditional build tools source the PKGBUILD directly in Bash just to read package metadata, which allows untrusted
recipes to run arbitrary commands before you ever see a prompt.
Shelly uses a purpose-built static parser that extracts variables, arrays, dependencies, and execution plans without
shell execution. It features a Bash-aware expansion engine supporting parameter expansions (${var#prefix},
${var/search/replace}, substring slicing), arithmetic expressions ($((...))), and brace expansions (pkg-{a,b}).
Any dynamic constructs that require runtime evaluation (such as command substitutions in integrity arrays) are isolated
and evaluated only after user approval in a controlled sandbox.
Shelly handles remote and local sources with strict security controls:
/var/cache/shelly/sources), avoiding duplicate downloads across rebuilds.sha512sums, sha256sums, b2sums,
etc.) and validates detached OpenPGP signatures. Pinned Git commits and tags are verified against deterministic
archive generation.makepkg relies on fakeroot (an LD_PRELOAD library) to intercept filesystem calls and pretend files are owned by
root:root inside $pkgdir.
Shelly replaces fakeroot with a virtual ownership engine:
package() execution
into an in-memory journal..PKGINFO, .MTREE, and .pkg.tar.zst archive
metadata.Shelly natively supports split PKGBUILD recipes containing multiple package_<pkgname>() functions:
pkgdesc, depends, backup, options) are
evaluated independently..pkg.tar.zst archive is assembled per package member.--package <member_name>.Shelly provides two levels of isolation for building untrusted recipes:
On modern Linux kernels (5.13+), Shelly can enforce filesystem isolation on build steps using the kernelβs Landlock Linux Security Module (LSM).
When enabled in shellybuild.conf:
prepare, pkgver, build, check, package) execute with restricted privileges via
prctl(NO_NEW_PRIVS).$HOME directory (including ~/.ssh, ~/.gnupg, and browser data)./usr, /etc, /opt, /tmp, /proc) and the build directory remain accessible.extra_read or extra_write.-i, --isolated)For complete clean-room isolation, pass -i or --isolated:
shelly build -iThis builds the package as an unprivileged user inside a fresh systemd-nspawn container root. It ensures no host files
or undeclared dependencies influence the compilation, mirroring official Arch package build environments.
Adding -l (--install) is safe here: the guest exports the archives and the host coordinator installs them, so the
container never writes into the host system database.
shellybuild.conf)shellybuild.conf is Shellyβs data-only TOML configuration file for the package builder. It replaces makepkg.conf for
Shellyβs native build engine.
Shelly merges configuration layers in the following order (later layers override earlier ones field-by-field):
/etc/shellybuild.conf$XDG_CONFIG_HOME/shelly/shellybuild.conf (or ~/.config/shelly/shellybuild.conf)--check, --sign, --package-destination) take final precedence.Below is the complete reference schema for shellybuild.conf with default values:
[build]# Target architecture and host tripletcarch = "x86_64"chost = "x86_64-pc-linux-gnu"
# Compiler and linker flags (arrays are joined with spaces during step execution)cppflags = []cflags = ["-O2", "-pipe"]cxxflags = ["-O2", "-pipe"]ldflags = ["-Wl,-z,relro", "-Wl,-z,now"]ltoflags = ["-flto=auto"]makeflags = ["-j2"]
# Default execution of check() test suitescheck = true
# Compiler cache and distributed compilation integrationsccache = falsedistcc = falsedistcc_hosts = []
[package]# Package metadata and compression formatpackager = "Unknown Packager"extension = ".pkg.tar.zst"
# Build options and tidy behavioroptions = ["strip", "docs", "emptydirs", "zipman", "purge", "lto"]strip_binaries = ["--strip-all"]strip_shared = ["--strip-debug"]strip_static = ["--strip-unneeded"]
# OpenPGP package signing defaultssign = falsesign_key = "0000000000000000000000000000000000000000"
[destinations]# Workspace and artifact storage locationsbuild = "/var/tmp/shellybuild"packages = "/var/cache/shelly/packages"sources = "/var/cache/shelly/sources"logs = "/var/log/shelly/build"
[sandbox]# Kernel Landlock LSM step confinementenabled = falseextra_read = []extra_write = [][build]makeflags: Concurrency and build options passed to make (e.g. ["-j$(nproc)"]).cflags / cxxflags / ldflags / ltoflags: Optimization and hardening flags exported to build child processes.ccache: When true, prepends /usr/lib/ccache/bin to PATH.distcc: When true, prepends /usr/lib/distcc/bin to PATH and exports DISTCC_HOSTS.[package]packager: Identifies the builder in .PKGINFO (e.g. "Jane Doe <[email protected]>").options: Controls package tidy operations. Supported options include strip, docs, emptydirs, zipman,
purge, lto, debug, libtool, and staticlibs. Recipes can override them using options=('!strip' '!purge').purge: Automatically removes usr/share/info/dir, .packlist files, and *.pod files from $pkgdir before
packing.sign / sign_key: Controls detached OpenPGP package signature generation.[destinations]build: Root directory for temporary extraction and compilation workspaces ($srcdir and $pkgdir).packages: Destination directory where finished .pkg.tar.zst archives are committed.sources: Cache directory for downloaded source tarballs and Git mirrors.logs: Directory where mandatory build logs are stored.[sandbox]enabled: Enables Landlock filesystem isolation for all build lifecycle steps.extra_read: List of absolute directory paths outside the standard system hierarchy granted read access (e.g.
["/home/user/.cargo/registry"]).extra_write: List of absolute directory paths granted read-write access (e.g. ["/home/user/.cache/ccache"]).--review-only)For CI/CD pipelines or static linting, evaluate a PKGBUILD and emit structured JSON metadata without downloading
sources or compiling:
shelly build --review-only ~/src/my-package/PKGBUILD--review-digest)Guarantee that automated builds compile the exact recipe reviewed by your team, preventing upstream tampering or race conditions:
# Specify the accepted 64-character SHA-256 review digestshelly build --review-digest "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" -r.SRCINFO Statically (--makesrcinfo)Generate a valid .SRCINFO file using Shellyβs fast static parser:
shelly build --makesrcinfo > .SRCINFOFor scripts, combine -n (--no-confirm) and -r (--reviewed):
shelly build -n -r -s--keep-workdirs)If a build fails and you need to inspect the $srcdir or $pkgdir staging trees, use the internal flag
--keep-workdirs:
shelly build --keep-workdirsWork directories are preserved in the configured build destination (/var/tmp/shellybuild/ by default) instead of
being cleaned up on exit.