SBUILD Specification
Complete reference for all SBUILD recipe fields. Each field is marked as:
- REQUIRED — must be present
- RECOMMENDED — optional but encouraged
- OPTIONAL — fully optional
Shebang & Control Fields
#!/SBUILD REQUIRED
All SBUILD recipes must begin with the #!/SBUILD shebang line. Optionally append a version assertion: #!/SBUILD ver @v1.0.0.
#!/SBUILD_disabled REQUIRED
Controls whether the recipe is enabled.
_disabled: falsePackage Identity
pkg REQUIRED
The canonical package name. Must be non-empty and contain only [a-zA-Z0-9+\-_.].
pkg: "clipcat"pkg_id RECOMMENDED
Unique package identifier. Same character constraints as pkg. If omitted, auto-derived from the first src_url entry (e.g. https://github.com/user/repo becomes github.com.user.repo).
pkg_id: "xrelkd.clipcat"INFO
When a repo produces multiple variants, append a tag: github.com.user.repo.stable, github.com.user.repo.nightly
pkg_type RECOMMENDED
The package format (must be lowercase). If empty, the runner reads magic bytes to determine the format automatically.
pkg_type: "static"Valid values: appimage, appbundle, archive, dynamic, flatimage, gameimage, nixappimage, runimage, static
app_id RECOMMENDED
AppStream App ID for desktop integration. Find it on Flathub or in AppStream metainfo.xml files.
app_id: "org.xrelkd.clipcat"INFO
This is not the same as pkg_id. app_id is for desktop integration, pkg_id is for identifying the package within PkgForge.
Version
pkgver OPTIONAL
Static package version string. Both pkgver and version are accepted as keys. When set, x_exec.pkgver is still used for update checking.
pkgver: "0.24.0"WARNING
Only use this if you want to pin a fixed version and update it manually. In most cases, let x_exec.pkgver determine the version dynamically.
Metadata
description REQUIRED
Package description. Can be a simple string or a mapping with per-program descriptions.
Simple string:
description: "A clipboard manager written in Rust"Per-program descriptions (when a recipe provides multiple programs):
description:
_default: "A toolset for network analysis"
nmap: "Network exploration and security auditing tool"
ncat: "Concatenation and redirection utility for networks"When using a mapping, _default is used as the primary description.
homepage OPTIONAL
Project homepage URLs (not the download page — that's src_url). Must have http, https, or ftp scheme.
homepage:
- "https://github.com/xrelkd/clipcat"src_url REQUIRED
Source/upstream URLs pointing to the download page or repository. Used for auto-deriving pkg_id if not set. Must have http, https, or ftp scheme.
src_url:
- "https://github.com/xrelkd/clipcat"category RECOMMENDED
FreeDesktop categories. Defaults to ["Utility"] if empty.
category:
- "System"
- "Utility"tag RECOMMENDED
Free-form metadata tags for better soar search results.
tag:
- "clipboard"
- "daemon"
- "rust"license OPTIONAL
License identifiers. Use SPDX identifiers when possible.
license:
- "GPL-3.0"
- "MIT"maintainer OPTIONAL
Author/maintainer of the SBUILD recipe (not the upstream package).
maintainer:
- "QaidVoid (contact@qaidvoid.dev)"note OPTIONAL
Extra information about the package. Certain flag prefixes have special meaning in metadata generation:
| Flag | Effect |
|---|---|
[DEPRECATED] | Marks the package as deprecated |
[EXTERNAL] | Filtered out of metadata |
[NO_INSTALL] | Filtered out of metadata |
[UNTRUSTED] | Filtered out of metadata |
[DO NOT RUN] | Filtered out of metadata |
note:
- "Official binary from https://github.com/xrelkd/clipcat"
- "[PORTABLE] (Portable Static Binary)"
- "[NO_DESKTOP_INTEGRATION]"repology RECOMMENDED
Repology project name(s) for version tracking.
repology:
- "clipcat"snapshots OPTIONAL
Snapshot version identifiers.
snapshots:
- "latest"Provides & Aliases
provides RECOMMENDED
Declares what binaries and packages a recipe produces. If empty, defaults to pkg.
provides:
- "clipcatd"
- "@clipcat-menu"
- "@clipcat-notify"
- "@clipcatctl"Syntax
| Syntax | Example | Meaning |
|---|---|---|
| Plain name | "clipcatd" | Package named clipcatd |
@ prefix | "@clipcat-menu" | Binary-only (not a separate package) |
: alias | "chaos:chaos-cli" | Package with search alias |
== symlink | "busybox==whoami" | Creates a symlink on install |
=> rename | "ripgrep=>rg" | Only the symlink is added to $PATH |
Entries prefixed with @ are excluded from the package list but included in the binary list.
In the example above:
- Packages:
["clipcatd"] - Binaries:
["clipcat-menu", "clipcat-notify", "clipcatctl"]
Multi-Package Recipes
packages OPTIONAL
For recipes that produce multiple distinct packages. When defined, takes precedence over the top-level provides field.
Each key is a package name, each value has a provides array:
packages:
clipcatd:
provides:
- "clipcatd"
clipcat-tools:
provides:
- "clipcatctl"
- "@clipcat-menu"
- "@clipcat-notify"Each sub-package gets its own output directory (packages/${package_name}/) during the build and is pushed as a separate GHCR artifact.
Build Configuration
build_asset OPTIONAL
Files to download before running x_exec.run. Downloaded in parallel to ${SBUILD_TMPDIR}. Each entry has url and out fields.
build_asset:
- url: "https://raw.githubusercontent.com/xrelkd/clipcat/main/LICENSE"
out: "LICENSE"
- url: "https://example.com/patch-${PKGVER}.diff"
out: "fix.patch"build_deps OPTIONAL
Build-time package dependencies (typically used with x_exec.container).
build_deps:
- "gcc"
- "openssl-dev"
- "musl-dev"build_util OPTIONAL
Static binaries to install via soar before the build. Only use if your distro doesn't provide the tool or you need the latest version.
build_util:
- "curl#bin"
- "jq#bin"ghcr_pkg REQUIRED
GHCR (GitHub Container Registry) package path used for publishing. Format: owner/package.
ghcr_pkg: "xrelkd/clipcat"Execution
x_exec REQUIRED
The core build/download logic.
x_exec:
host:
- "x86_64-linux"
- "aarch64-linux"
shell: "bash"
pkgver: |
curl -qfsSL "https://api.github.com/repos/owner/repo/releases/latest" | jq -r '.tag_name'
run: |
# Build or download the package
# Output must be placed in ${SBUILD_OUTDIR}x_exec.shell REQUIRED
Shell interpreter for run and pkgver scripts. Must exist in PATH (unless container is specified).
x_exec:
shell: "bash"TIP
Prefer sh or bash for maximum portability across build environments.
x_exec.run REQUIRED
The build/download script. Must produce the required output files in ${SBUILD_OUTDIR}. Validated by ShellCheck.
x_exec:
run: |
soar dl "https://github.com/xrelkd/clipcat@v${PKGVER}" \
--glob "*${ARCH}-unknown-linux-musl.tar.gz" --yes -o clipcat.tar.gz
tar -xf "clipcat.tar.gz" -C "$SBUILD_TMPDIR/"
mv "$SBUILD_TMPDIR/clipcatd" "$SBUILD_OUTDIR/clipcatd"
mv "$SBUILD_TMPDIR/clipcatctl" "$SBUILD_OUTDIR/clipcatctl"x_exec.pkgver OPTIONAL
Script to dynamically fetch the upstream version. Output:
- Line 1: Package version (required)
- Line 2: Remote version tag (optional, exported as
${REMOTE_PKGVER}for use inrun)
The package version from line 1 is exported as ${PKGVER}.
x_exec:
pkgver: |
VERSION=$(curl -qfsSL "https://api.github.com/repos/xrelkd/clipcat/releases/latest" | jq -r '.tag_name')
echo "${VERSION#v}"
echo "$VERSION"x_exec.host OPTIONAL
Combined arch + os restriction. Preferred over separate arch/os fields. Build terminates if the host doesn't match.
x_exec:
host:
- "x86_64-linux"
- "aarch64-linux"Valid architectures: x86_64, aarch64, riscv64, loongarch64
Valid operating systems: linux, freebsd, openbsd, netbsd, illumos, redox
x_exec.arch OPTIONAL
Restrict to specific architectures (use host instead when possible).
x_exec:
arch:
- "aarch64"
- "x86_64"x_exec.os OPTIONAL
Restrict to specific operating systems (use host instead when possible).
x_exec:
os:
- "linux"x_exec.container OPTIONAL
Container image for the build environment. When specified, shell PATH validation is bypassed.
x_exec:
container: "alpine:edge"x_exec.entrypoint OPTIONAL
Override the container entrypoint.
x_exec:
entrypoint: "/bin/sh"x_exec.conflicts OPTIONAL
Packages to uninstall after a successful build (case-insensitive, lowercased).
x_exec:
conflicts:
- "clipcat-git"x_exec.depends OPTIONAL
Runtime dependencies to install before x_exec.run (case-insensitive, lowercased).
x_exec:
depends:
- "dbus"
- "xorg-xclip"Validation Rules
- Required fields
_disabled,pkg,description,src_url,ghcr_pkg, andx_execmust be present - Name fields (
pkg,pkg_id,app_id) only allow[a-zA-Z0-9+\-_.] - URL fields (
src_url,homepage,build_asset.url) must havehttp,https, orftpscheme - Duplicate array entries are automatically removed with a warning
- Empty required fields produce a fatal validation error
- Shell scripts (
run,pkgver) are validated by shellcheck hosttriples must match{valid_arch}-{valid_os}formatpackagesmust not be empty if defined; each sub-package must have at least oneprovidesentry
Complete Example
A full recipe demonstrating most fields (from soarpkgs):
#!/SBUILD
_disabled: false
pkg: "clipcat"
pkg_id: "xrelkd.clipcat"
app_id: "org.xrelkd.clipcat"
pkg_type: "static"
ghcr_pkg: "xrelkd/clipcat"
category:
- "System"
- "Utility"
description: "A clipboard manager written in Rust"
homepage:
- "https://github.com/xrelkd/clipcat"
maintainer:
- "QaidVoid (contact@qaidvoid.dev)"
license:
- "GPL-3.0"
note:
- "Official binary from https://github.com/xrelkd/clipcat"
- "[PORTABLE] (Portable Static Binary)"
- "[NO_DESKTOP_INTEGRATION]"
provides:
- "clipcatd"
- "@clipcat-menu"
- "@clipcat-notify"
- "@clipcatctl"
repology:
- "clipcat"
src_url:
- "https://github.com/xrelkd/clipcat"
tag:
- "clipboard"
- "daemon"
- "rust"
- "cli"
snapshots:
- "latest"
build_asset:
- url: "https://raw.githubusercontent.com/xrelkd/clipcat/main/LICENSE"
out: "LICENSE"
build_util:
- "jq"
- "curl"
x_exec:
host:
- "x86_64-linux"
- "aarch64-linux"
shell: "sh"
depends:
- "dbus"
conflicts:
- "clipcat-git"
pkgver: |
curl -qfsSL "https://api.github.com/repos/xrelkd/clipcat/releases/latest" \
| jq -r '.tag_name' | tr -d 'v'
run: |
soar dl "https://github.com/xrelkd/clipcat@v${PKGVER}" \
--glob "*${ARCH}-unknown-linux-musl.tar.gz" --yes -o clipcat.tar.gz
tar -xf "clipcat.tar.gz" -C "$SBUILD_TMPDIR/"
mv "$SBUILD_TMPDIR/clipcat-menu" "$SBUILD_OUTDIR/clipcat-menu"
mv "$SBUILD_TMPDIR/clipcat-notify" "$SBUILD_OUTDIR/clipcat-notify"
mv "$SBUILD_TMPDIR/clipcatctl" "$SBUILD_OUTDIR/clipcatctl"
mv "$SBUILD_TMPDIR/clipcatd" "$SBUILD_OUTDIR/clipcatd"
rm -rf "clipcat.tar.gz"Multi-Package Variant
The same recipe using packages instead of provides, built inside a container:
#!/SBUILD
_disabled: false
pkg: "clipcat"
pkg_id: "xrelkd.clipcat"
pkg_type: "static"
ghcr_pkg: "xrelkd/clipcat"
description: "A clipboard manager written in Rust"
src_url:
- "https://github.com/xrelkd/clipcat"
packages:
clipcatd:
provides:
- "clipcatd"
clipcat-tools:
provides:
- "clipcatctl"
- "@clipcat-menu"
- "@clipcat-notify"
x_exec:
host:
- "x86_64-linux"
- "aarch64-linux"
shell: "sh"
depends:
- "dbus"
pkgver: |
curl -qfsSL "https://api.github.com/repos/xrelkd/clipcat/releases/latest" \
| jq -r '.tag_name' | tr -d 'v'
run: |
soar dl "https://github.com/xrelkd/clipcat@v${PKGVER}" \
--glob "*${ARCH}-unknown-linux-musl.tar.gz" --yes -o clipcat.tar.gz
tar -xf "clipcat.tar.gz" -C "$SBUILD_TMPDIR/"
mkdir -p "$SBUILD_OUTDIR/packages/clipcatd" "$SBUILD_OUTDIR/packages/clipcat-tools"
mv "$SBUILD_TMPDIR/clipcatd" "$SBUILD_OUTDIR/packages/clipcatd/clipcatd"
mv "$SBUILD_TMPDIR/clipcatctl" "$SBUILD_OUTDIR/packages/clipcat-tools/clipcatctl"
mv "$SBUILD_TMPDIR/clipcat-menu" "$SBUILD_OUTDIR/packages/clipcat-tools/clipcat-menu"
mv "$SBUILD_TMPDIR/clipcat-notify" "$SBUILD_OUTDIR/packages/clipcat-tools/clipcat-notify"
rm -rf "clipcat.tar.gz"