yap — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited yap (Plugin) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<div align="center">
<img src="assets/images/logo.png" alt="yap-logo" width="240">
<br><br>
</div>
YAP builds native packages for multiple GNU/Linux distributions from a single PKGBUILD specification. Write your package once; get .deb, .rpm, .apk, and .pkg.tar.zst out. All builds run in isolated OCI containers (Docker or Podman).
--parallelgpg binary required)zstd/gzip/xz for DEB and RPMchangelog PKGBUILD field renders to native format per distroOne-liner (Linux/macOS, amd64/arm64):
curl -fsSL https://raw.githubusercontent.com/M0Rf30/yap/main/scripts/install.sh | shPin a version or install only one tool:
curl -fsSL https://raw.githubusercontent.com/M0Rf30/yap/main/scripts/install.sh \
| sh -s -- --version v2.1.3 --tool yapManual download:
wget https://github.com/M0Rf30/yap/releases/latest/download/yap_Linux_x86_64.tar.gz
tar -xzf yap_Linux_x86_64.tar.gz
sudo mv yap /usr/local/bin/
yap versiongit clone https://github.com/M0Rf30/yap.git
cd yap
make build
sudo mv yap /usr/local/bin/Requires Docker or Podman:
# Docker
sudo systemctl enable --now docker && sudo usermod -aG docker $USER
# Podman
sudo systemctl enable --now podmanCreate yap.json:
{
"name": "My Package",
"description": "A sample package built with YAP",
"buildDir": "/tmp/yap-build",
"output": "artifacts",
"projects": [
{ "name": "my-package" }
]
}Create my-package/PKGBUILD:
pkgname=my-package
pkgver=1.0.0
pkgrel=1
pkgdesc="My awesome application"
arch=('x86_64')
license=('GPL-3.0')
url="https://github.com/user/my-package"
makedepends=('gcc' 'make')
source=("https://github.com/user/my-package/archive/v${pkgver}.tar.gz")
sha256sums=('SKIP')
build() {
cd "${srcdir}/${pkgname}-${pkgver}"
make
}
package() {
cd "${srcdir}/${pkgname}-${pkgver}"
install -Dm755 my-package "${pkgdir}/usr/bin/my-package"
install -Dm644 README.md "${pkgdir}/usr/share/doc/${pkgname}/README.md"
}# Auto-detect host distro from /etc/os-release
yap build .
# Specific distribution
yap build ubuntu-jammy .
yap build fedora-38 /path/to/project
yap build --cleanbuild --no-makedeps ubuntu-jammy .artifacts/
├── my-package_1.0.0-1_amd64.deb
├── my-package-1.0.0-1.x86_64.rpm
├── my-package-1.0.0-r1.apk
└── my-package-1.0.0-1-x86_64.pkg.tar.zstyap.json){
"name": "My Multi-Package Project",
"description": "Project description",
"buildDir": "/tmp/yap-builds",
"output": "dist",
"projects": [
{ "name": "package-one", "install": true },
{ "name": "package-two" }
]
}| Field | Required | Default | Description |
|---|---|---|---|
name | yes | — | Project collection name |
description | yes | — | Project collection description |
buildDir | yes | — | Build/working directory |
output | yes | — | Output directory for built packages |
projects | yes | — | Ordered array of packages to build |
projects[].name | yes | — | Sub-directory containing the package's PKGBUILD |
projects[].install | no | false | Install immediately after build so later packages can depend on it |
compressionDeb / compressionRpm | no | zstd | Per-format compression: zstd/gzip/xz |
signing | no | — | Signing config (see Package signing) |
repos | no | — | Extra package repositories to configure before resolving deps |
skipDeps | no | — | Package names to omit from makedepends |
targetArch | no | host | Cross-compilation target architecture |
parallel | no | false | Build independent packages in parallel (topo-sort) |
sbom | no | false | Generate SBOM sidecars |
sbomFormat | no | both | cyclonedx/spdx/both |
Build ordering between packages comes from the install flag and each PKGBUILD's depends/makedepends — there is no yap.json-level depends field. See yap.schema.json for the complete spec.
A JSON Schema for yap.json ships at the repo root: yap.schema.json. It documents every supported field (compression, signing, repos, SBOM, cross-compilation, etc.). Reference it from your yap.json for autocomplete and inline validation in editors that support JSON Schema:
{
"$schema": "https://www.schemastore.org/yap.json",
"name": "My Multi-Package Project",
"...": "..."
}The schema is published on SchemaStore, so editors (VS Code, JetBrains, Neovim, …) validate any yap.json by filename automatically — no $schema line required.
Use __ (double underscore) to override any variable per distribution. Priority (highest wins):
| Priority | Syntax | Example |
|---|---|---|
| 4+ | arch + distro | depends_x86_64__ubuntu_noble |
| 4 | arch only | depends_x86_64 |
| 3 | distro + codename | depends__ubuntu_noble |
| 2 | distro | depends__ubuntu |
| 1 | package manager | depends__apt |
| 0 | base (fallback) | depends |
pkgdesc="My application"
pkgdesc__debian="My application for Debian/Ubuntu"
pkgdesc__ubuntu_noble="My application optimized for Ubuntu 24.04"
makedepends=('gcc' 'make')
makedepends__apt=('build-essential' 'cmake')
makedepends__yum=('gcc-c++' 'cmake3')
makedepends__ubuntu_noble=('build-essential' 'cmake' 'pkg-config' 'libtool')depends=('glibc' 'gcc')
depends_x86_64=('glibc' 'gcc' 'lib32-glibc')
depends_aarch64=('glibc' 'gcc' 'aarch64-linux-gnu-gcc')
source=('https://example.com/generic-source.tar.gz')
source_x86_64=('https://example.com/x86_64-optimized.tar.gz')
source_aarch64=('https://example.com/aarch64-source.tar.gz')
sha256sums=('generic_hash')
sha256sums_x86_64=('x86_64_specific_hash')
sha256sums_aarch64=('aarch64_specific_hash')Supported architectures: x86_64, i686, aarch64, armv7h, armv6h, armv5, ppc64, ppc64le, s390x, mips, mipsle, riscv64, pentium4, any.
Supported (strongest to fastest): b2sums, sha512sums, sha384sums, sha256sums, sha224sums, cksums.
# BLAKE2b (recommended)
b2sums=('2f240f2a3d2f8d8f...')
# CRC32 (format: checksum filesize)
cksums=('1234567890 2048576')changelog=CHANGELOG.mdusr/share/doc/<pkgname>/changelog.Debian.gz (Lintian-compliant)%changelog entries embedded in package metadata.CHANGELOG in the archivepre_install() { echo "Before install"; }
post_install() { systemctl daemon-reload; }
pre_upgrade() { systemctl stop myservice; }
post_upgrade() { systemctl start myservice; }
pre_remove() { systemctl disable myservice; }
post_remove() { systemctl daemon-reload; }Emitted to <pkgname>.install only when at least one hook is defined. pre/post_upgrade fall back to pre/post_install when absent.
# DEB
section=utils
priority=optional
# RPM
group="Applications/System"
requires_pre=('shadow-utils')
# APK
maintainer="John Doe <[email protected]>"| Distribution ID | Format | Package Manager |
|---|---|---|
almalinux | .rpm | yum |
alpine | .apk | apk |
amzn | .rpm | yum |
arch | .pkg.tar.zst | pacman |
centos | .rpm | yum |
debian | .deb | apt |
fedora | .rpm | yum |
linuxmint | .deb | apt |
opensuse-leap | .rpm | zypper |
opensuse-tumbleweed | .rpm | zypper |
ol | .rpm | yum |
pop | .deb | apt |
rhel | .rpm | yum |
rocky | .rpm | yum |
ubuntu | .deb | apt |
YAP ships a companion yap-mcp binary that exposes the same build pipeline over the Model Context Protocol, so any MCP-compatible LLM client (Claude Desktop, opencode, Cursor, Zed, Continue, Goose, …) can drive yap directly.
Quickstart (release binary):
curl -fsSL https://raw.githubusercontent.com/M0Rf30/yap/main/scripts/install.sh | sh
# then add { "mcpServers": { "yap": { "command": "yap-mcp" } } } to your client configOr pull the standalone OCI image (also listed on the MCP registry as io.github.M0Rf30/yap):
docker pull ghcr.io/m0rf30/yap-mcp:latest
# client config:
# { "mcpServers": { "yap": { "command": "docker",
# "args": ["run","-i","--rm","ghcr.io/m0rf30/yap-mcp:latest"] } } }/plugin marketplace add M0Rf30/claude-plugins
/plugin install yap@M0Rf30npx @smithery/cli install io.github.M0Rf30/yap --client claudeThe full tool surface, per-client config snippets, security model, and troubleshooting are in [`MCP.md`](MCP.md). The shipped skill card at skills/yap/SKILL.md follows the Anthropic Agent Skills layout and gives agents a workflow cheatsheet for free. Distribution channels and release steps are documented in [`PUBLISHING.md`](PUBLISHING.md).
yap build [distro[-release]] <path> # Build packages (distro auto-detected if omitted)
yap zap [distro] <path> # Clean build environment
yap prepare [distro[-release]] # Prepare host build environment
yap pull <distro> # Pull pre-built container images
yap install <artifact-file> # Install a built artifact
yap graph [path] # Show dependency graph
yap list-distros # List supported distributions
yap status # Show host status and runtime detection
yap version # Show version information
yap completion <shell> # Generate shell completion (bash/zsh/fish/powershell)# Build behavior
--cleanbuild, -c # Clean srcdir before build
--no-build, -o # Download sources only
--zap, -z # Deep clean staging directory
--skip-hash-check, -H # Skip source checksum verification
--no-container # Build natively on the host (skip container dispatch)
# Dependencies
--no-makedeps, -d # Skip makedeps installation
--skip-sync, -s # Skip package manager sync
--skip-deps pkg1,pkg2 # Omit specific packages from makedeps
--parallel, -P # Enable parallel topo-sort (opt-in)
# Version
--pkgver 1.2.3, -w # Override package version
--pkgrel 2, -r # Override release number
# Range / filter
--from package1 # Start from specific package
--to package5 # Stop at specific package
--only pkg1,pkg2 # Build only listed packages
--skip pkg1,pkg2 # Skip listed packages
# Source access
--ssh-password pass, -p # Password for SSH source access
# Cross-compilation
--target-arch arm64, -t # Cross-compile for target architecture
--skip-toolchain-validation, -T
# Repositories / trust
--repo "<spec>" # Add an extra package repository (repeatable)
--allow-unverified-repos, -U # Allow apt sources without a verifiable Signed-By key
# Signing
--sign, -K # Enable artifact signing
--sign-key /path/to/key # Private key path
--sign-passphrase pass # Passphrase (prefer env: YAP_SIGN_PASSPHRASE)
--sign-key-name mykey # APK key name
# SBOM
--sbom, -S # Generate SBOM sidecars
--sbom-format cyclonedx # CycloneDX 1.5 only
--sbom-format spdx # SPDX 2.3 only
--sbom-format both # Both (default)
# Compression
--compression-deb gzip # DEB: zstd|gzip|xz (default: zstd)
--compression-rpm xz # RPM: zstd|gzip|xz (default: zstd)
# Debug / output
--debug-dir /path, -D # Emit split debug info
--verbose # Verbose logging
--no-color # Disable colored outputyap completion bash > /etc/bash_completion.d/yap
yap completion zsh > /usr/share/zsh/site-functions/_yap
yap completion fish > ~/.config/fish/completions/yap.fish
yap completion powershell > yap.ps1| Format | Algorithm | Output |
|---|---|---|
| APK | RSA PKCS#1 v1.5 SHA1 | .SIGN.RSA.<keyname>.rsa.pub embedded stream |
| DEB | OpenPGP | <package>.deb.asc (ASCII-armored detached) |
| RPM | OpenPGP | <package>.rpm.asc + optional in-RPM via rpmpack |
| Pacman | OpenPGP | <package>.pkg.tar.zst.sig (binary detached) |
Signing uses github.com/ProtonMail/go-crypto/openpgp — no gpg binary required.
--sign-key <path> CLI flagYAP_APK_KEY, YAP_DEB_KEY, YAP_RPM_KEY, YAP_PACMAN_KEYYAP_SIGN_KEYyap.json field signing.keyPath~/.config/yap/keys/<format>.{rsa,gpg} then ~/.config/yap/keys/default.{rsa,gpg}Passphrase resolution mirrors key resolution with _PASSPHRASE suffix.
{
"signing": {
"enabled": true,
"keyPath": "~/.config/yap/keys/release.gpg",
"keyName": "release"
}
}# APK (after distributing the public key to /etc/apk/keys/)
apk add my-package.apk
# DEB
gpg --verify my-package_1.0.0_amd64.deb.asc my-package_1.0.0_amd64.deb
# RPM
rpm -K my-package-1.0.0-1.x86_64.rpm
# Pacman
pacman-key --verify my-package-1.0.0-1-x86_64.pkg.tar.zst.sigyap build --sbom . # Both formats (default)
yap build --sbom --sbom-format cyclonedx .
yap build --sbom --sbom-format spdx .Output alongside each artifact:
artifacts/
└── my-package_1.0.0-1_amd64.deb
my-package_1.0.0-1_amd64.deb.cdx.json ← CycloneDX 1.5
my-package_1.0.0-1_amd64.deb.spdx.json ← SPDX 2.3Captured: name, version, license, runtime/build deps, source URLs and checksums, file hashes, DESCRIBES/DEPENDS_ON relationships.
yap build --target-arch=aarch64 ubuntu-jammy .
yap build --target-arch=armv7 fedora-38 .
yap build --target-arch=i686 alpine .
yap build --target-arch=ppc64le arch .YAP installs the required cross-compilation toolchains and configures the build environment automatically.
{
"name": "My Suite",
"projects": [
{ "name": "core-library", "install": true },
{ "name": "main-application", "install": true },
{ "name": "plugins", "install": false }
]
}Packages with "install": true are installed immediately after building so subsequent packages can use them as build-time dependencies.
# Sequential (default) — explicit ordering via "install" field
yap build .
# Parallel — topo-sort + worker pool
yap build --parallel .yap prepare # Auto-detect host distro
yap prepare ubuntu-jammy
yap prepare fedora-38
yap prepare --golang arch
yap prepare --skip-sync rocky-9#### GitHub Actions
name: Build Packages
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install YAP
run: |
wget https://github.com/M0Rf30/yap/releases/latest/download/yap_Linux_x86_64.tar.gz
tar -xzf yap_Linux_x86_64.tar.gz
sudo mv yap /usr/local/bin/
- name: Build Packages
run: yap build
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: packages
path: artifacts/#### GitLab CI
build-packages:
stage: build
image: ubuntu:22.04
before_script:
- apt-get update && apt-get install -y wget docker.io
- wget https://github.com/M0Rf30/yap/releases/latest/download/yap_Linux_x86_64.tar.gz
- tar -xzf yap_Linux_x86_64.tar.gz && mv yap /usr/local/bin/
script:
- yap build
artifacts:
paths:
- artifacts/
expire_in: 1 weekThe examples directory contains complete, ready-to-build projects:
| Example | Description |
|---|---|
| circular-deps | Circular dependency detection — YAP fails with a clear error |
| dependency-orchestration | 5-package project with automatic dep resolution and build ordering |
| yap | YAP packaging itself — Go application with install scripts |
| split-package | One build producing multiple installable packages with distro overrides |
| multi-architecture | Architecture-specific sources, deps, and checksums |
pkgname=hello-world
pkgver=1.0.0
pkgrel=1
pkgdesc="A simple Hello World program"
arch=('x86_64')
license=('MIT')
makedepends=('gcc')
source=("hello.c")
sha256sums=('SKIP')
build() { gcc -o hello hello.c; }
package() { install -Dm755 hello "${pkgdir}/usr/bin/hello"; }pkgname=python-myapp
pkgver=2.1.0
pkgrel=1
pkgdesc="My Python application"
arch=('any')
license=('Apache-2.0')
depends=('python3')
makedepends__apt=('python3-dev' 'python3-setuptools')
makedepends__yum=('python3-devel' 'python3-setuptools')
source=("https://pypi.io/packages/source/m/myapp/myapp-${pkgver}.tar.gz")
sha256sums=('...')
build() {
cd "${srcdir}/myapp-${pkgver}"
python3 setup.py build
}
package() {
cd "${srcdir}/myapp-${pkgver}"
python3 setup.py install --root="${pkgdir}" --optimize=1
}pkgname=web-service
pkgver=1.5.0
pkgrel=1
pkgdesc="My web service"
arch=('x86_64')
license=('GPL-3.0')
depends=('systemd')
backup=('etc/web-service/config.yml')
source=("web-service-${pkgver}.tar.gz" "web-service.service")
sha256sums=('...' 'SKIP')
build() {
cd "${srcdir}/web-service-${pkgver}"
make build
}
package() {
cd "${srcdir}/web-service-${pkgver}"
install -Dm755 web-service "${pkgdir}/usr/bin/web-service"
install -Dm644 ../web-service.service \
"${pkgdir}/usr/lib/systemd/system/web-service.service"
install -Dm644 config.yml "${pkgdir}/etc/web-service/config.yml"
install -dm755 "${pkgdir}/var/lib/web-service"
install -dm755 "${pkgdir}/var/log/web-service"
}make all # clean, deps, fmt, lint, test, doc, build
make build # build the yap binary
make build-all # build for linux/darwin/windows, amd64/arm64
make clean # clean build artifacts
make deps # download and tidy Go modules
make fmt # gofmt
make lint # golangci-lint
make lint-md # markdownlint
make test # run all tests (-p 1 -v, sequential required)
make test-coverage # tests with coverage report (coverage.html)
make release # create release packages
make doc # view all package documentation
make doc-serve # start pkgsite on localhost:8080
make doc-generate # generate static docs in docs/api/
make doc-package PKG=./pkg/builders/apk
make docker-build DISTRO=ubuntu
make docker-build-all
make docker-list-distros
make i18n-check # verify localization file integrity
make i18n-stats # localization statisticsTests must run sequentially (-p 1):
make test
go test ./pkg/source -v
go test ./pkg/builders/deb -v
go test ./pkg/graph -v
go test -race ./pkg/builders/...
go test -timeout 30s ./pkg/download/...Supported languages: English (en), Italian (it).
Language is auto-detected from LANG/LC_ALL/LC_MESSAGES/LANGUAGE. Override with --language / -l:
yap --language=it build .To add a language: copy pkg/i18n/locales/en.yaml to pkg/i18n/locales/{code}.yaml, translate, add the code to SupportedLanguages in pkg/i18n/i18n.go, submit a PR.
systemctl status docker # or podman
docker run --rm hello-world # test access
sudo usermod -aG docker $USER # fix permissions (re-login required)yap build --verbose
yap zap ubuntu-jammy /path/to/project
yap statussudo chown -R $USER:$USER artifacts/
setsebool -P container_manage_cgroup true # SELinux (Red Hat family)yap build --skip-sync # skip package manager sync
yap build --cleanbuild # clean source before buildgit checkout -b feature/my-featuremake fmt lint testSee CODE_OF_CONDUCT.md for community guidelines.
GNU General Public License v3.0. See LICENSE.md.
Built with Go, Cobra, Docker / Podman.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.