YAP — Yet Another Packager
Build native Linux packages (.deb/.rpm/.apk/.pkg.tar.zst) from a single PKGBUILD via MCP.
What can you do with YAP — Yet Another Packager?
- Multi-format output: DEB (Debian/Ubuntu), RPM (Fedora/RHEL/Rocky/openSUSE), APK (Alpine), TAR.ZST (Arch)
- Container isolation: reproducible builds, no host contamination, Docker and Podman supported
- PKGBUILD-based: familiar Arch Linux syntax extended with distribution and architecture overrides
- Cross-compilation: build for a different architecture than your host
- Dependency-aware builds: sequential by default; opt-in parallel topo-sort via
--parallel - Package signing: APK RSA + DEB/RPM/Pacman GPG (no
gpgbinary required) - SBOM generation: CycloneDX 1.5 and SPDX 2.3 sidecars
- Publishing:
yap publishuploads DEB/RPM (and APK/Pacman as raw files) to an OpenArtifact repository
Install
Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).
ghcr.io/m0rf30/yap-mcp:2.8.0claude mcp add yap-yet-another-packager -e 'YAP_VERBOSE=<YAP_VERBOSE>' -- docker run -i --rm ghcr.io/m0rf30/yap-mcp:2.8.0
{
"mcpServers": {
"yap-yet-another-packager": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/m0rf30/yap-mcp:2.8.0"
],
"env": {
"YAP_VERBOSE": "<YAP_VERBOSE>"
}
}
}
}
Environment variables
YAP_VERBOSESet to 1 for debug-level JSON-RPC frame logging on stderr.
Documentation
From the project's README on GitHub, refreshed weekly. Links open on GitHub.
Contents
- YAP — Yet Another Packager
- Features
- Installation
- Quick start
- Project configuration (yap.json)
- PKGBUILD extensions
- Supported distributions
- Model Context Protocol (MCP)
- CLI reference
- Package signing
- Publishing to OpenArtifact
- SBOM generation
- Advanced usage
- Examples
- PKGBUILD examples
- Development
- Troubleshooting
- Contributing
- License
- Credits
YAP — Yet Another Packager
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).
Features
- Multi-format output: DEB (Debian/Ubuntu), RPM (Fedora/RHEL/Rocky/openSUSE), APK (Alpine), TAR.ZST (Arch)
- Container isolation: reproducible builds, no host contamination, Docker and Podman supported
- PKGBUILD-based: familiar Arch Linux syntax extended with distribution and architecture overrides
- Cross-compilation: build for a different architecture than your host
- Dependency-aware builds: sequential by default; opt-in parallel topo-sort via
--parallel - Package signing: APK RSA + DEB/RPM/Pacman GPG (no
gpgbinary required) - SBOM generation: CycloneDX 1.5 and SPDX 2.3 sidecars
- Publishing:
yap publishuploads DEB/RPM (and APK/Pacman as raw files) to an OpenArtifact repository - Per-format compression:
zstd/gzip/xzfor DEB and RPM - Changelog support:
changelogPKGBUILD field renders to native format per distro - Pacman scriptlets: full 6-hook lifecycle (pre/post install/upgrade/remove)
- Structured logging: slog-based, tree rendering for long lines, zero external UI deps
Installation
One-liner (Linux/macOS, amd64/arm64):
curl -fsSL https://raw.githubusercontent.com/M0Rf30/yap/main/scripts/install.sh | sh
Pin 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 yap
Manual 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 version
Build from source
git 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 podman
Quick start
1. Project structure
Create yap.json:
{
"name": "My Package",
"description": "A sample package built with YAP",
"buildDir": "/tmp/yap-build",
"output": "artifacts",
"projects": [
{ "name": "my-package" }
]
}
2. PKGBUILD
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"
}
3. Build
# 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 .
4. Output
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.zst
Project configuration (yap.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 |
publish | no | — | Defaults for yap publish (see Publishing); never holds the token |
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.
Editor validation (JSON Schema)
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.
PKGBUILD extensions
Distribution-specific variables
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')
Architecture-specific variables
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.
Checksum types
Supported (strongest to fastest): b2sums, sha512sums, sha384sums, sha256sums, sha224sums, cksums.
# BLAKE2b (recommended)
b2sums=('2f240f2a3d2f8d8f...')
# CRC32 (format: checksum filesize)
cksums=('1234567890 2048576')
Changelog
changelog=CHANGELOG.md
- DEB:
usr/share/doc/<pkgname>/changelog.Debian.gz(Lintian-compliant) - RPM: native
%changelogentries embedded in package metadata - Pacman:
.CHANGELOGin the archive - APK: ignored (no Alpine convention)
Pacman scriptlets
pre_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.
Package manager-specific fields
# DEB
section=utils
priority=optional
# RPM
group="Applications/System"
requires_pre=('shadow-utils')
# APK
maintainer="John Doe <john@example.com>"
Supported distributions
| 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 |
Model Context Protocol (MCP)
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 config
Or 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"] } } }
Claude Code plugin (server + skill in one)
/plugin marketplace add M0Rf30/claude-plugins
/plugin install yap@M0Rf30
Smithery
npx @smithery/cli install io.github.M0Rf30/yap --client claude
The full tool surface, per-client config snippets, security model, and
troubleshooting are in 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.
CLI reference
Commands
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 publish [artifact-or-dir]... # Upload built packages to an OpenArtifact repository
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 flags
# 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
--source-retries <n> # Retries after first attempt for source/gensum/toolchain downloads (default 3; env: YAP_SOURCE_MAX_RETRIES)
# 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 output
Shell completion
yap 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
Package signing
| 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.
Key resolution (highest to lowest)
--sign-key <path>CLI flag- Format env:
YAP_APK_KEY,YAP_DEB_KEY,YAP_RPM_KEY,YAP_PACMAN_KEY - Global env:
YAP_SIGN_KEY yap.jsonfieldsigning.keyPath~/.config/yap/keys/<format>.{rsa,gpg}then~/.config/yap/keys/default.{rsa,gpg}
Passphrase resolution mirrors key resolution with _PASSPHRASE suffix.
yap.json signing config
{
"signing": {
"enabled": true,
"keyPath": "~/.config/yap/keys/release.gpg",
"keyName": "release"
}
}
Verifying signed packages
# 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.sig
Publishing to OpenArtifact
yap publish uploads built packages to a hosted
OpenArtifact repository, which
serves the apt/dnf indexes (Release, Packages, repomd.xml) itself.
| Format | Route used | Notes |
|---|---|---|
| DEB | POST {url}/api/v1/repositories/{deb-repo}/debs | multipart file, distribution, component |
| RPM | POST {url}/api/v1/repositories/{rpm-repo}/packages | multipart file |
| APK | PUT {url}/repos/raw/{apk-repo}/{apk-path}/{file} | hosted raw repository; OpenArtifact has no apk index yet |
| Pacman | PUT {url}/repos/raw/{pacman-repo}/{pacman-path}/{file} | raw repository; the .sig/.asc sidecars next to a package are uploaded too |
export YAP_OA_URL=https://oa.example.com
export YAP_OA_TOKEN_FILE=~/.config/yap/oa-token # or YAP_OA_TOKEN
export YAP_OA_DEB_REPO=debs YAP_OA_RPM_REPO=rpms
yap build ubuntu-jammy .
yap publish --distribution jammy --component main ./dist # or a single file
yap publish --dry-run ./dist # list only, no network
Settings resolve in this order (later wins): the publish object of
yap.json, the YAP_OA_* environment, command-line flags.
{
"output": "dist",
"publish": {
"url": "https://oa.example.com",
"debRepo": "debs",
"rpmRepo": "rpms",
"distribution": "jammy",
"component": "main"
}
}
| Setting | yap.json | Environment | Flag |
|---|---|---|---|
| Server URL | url | YAP_OA_URL | --url |
| API token | — | YAP_OA_TOKEN, YAP_OA_TOKEN_FILE | --token-file |
| DEB repo | debRepo | YAP_OA_DEB_REPO | --deb-repo |
| RPM repo | rpmRepo | YAP_OA_RPM_REPO | --rpm-repo |
| APK raw repo / path | apkRepo / apkPath | YAP_OA_APK_REPO / YAP_OA_APK_PATH | --apk-repo / --apk-path |
| Pacman raw repo / path | pacmanRepo / pacmanPath | YAP_OA_PACMAN_REPO / YAP_OA_PACMAN_PATH | --pacman-repo / --pacman-path |
| apt distribution / component | distribution / component | YAP_OA_DISTRIBUTION / YAP_OA_COMPONENT | --distribution / --component |
Other flags: --config <yap.json|dir> (default ./yap.json), --retries <n>
(attempts per request, default 3), --timeout <duration> (per request, default
30m), --insecure-http, --dry-run.
Behaviour:
- Token: an OpenArtifact API token with write permission on the target
repositories (a
deploytoken,oa_dep_…, is enough). It is sent asAuthorization: Bearer …, is never accepted fromyap.jsonor a flag value (so it stays out of the process list), and is redacted from logs and errors. The token is only sent overhttps, orhttpto a loopback host unless you pass--insecure-http. - Arguments: package files and/or directories. Without arguments the
outputdirectory ofyap.jsonis published. Packages found while scanning a directory whose format has no repository configured are skipped with a warning; an explicitly named file in that situation is an error. - Verification: the SHA-256 returned by the server (or
X-Checksum-Sha256for raw files) must equal the local file's, otherwise the publish fails. - Retries: connection errors and HTTP 408/429/5xx are retried with exponential backoff and jitter; other 4xx answers (bad token, wrong repository, invalid package) fail immediately.
- Idempotent: DEB/RPM packages are immutable on the server, which answers
409. yap then looks the SHA-256 up in the repository listing: identical bytes count as success ("unchanged"), different bytes under the same name and version fail. Raw files are skipped whenX-Checksum-Sha256already matches and replaced otherwise (unless the repository enforces immutable releases, which fails the publish). - Signatures: OpenArtifact signs repository indexes; yap's per-package
.ascfiles are not uploaded for DEB/RPM. For APK/Pacman raw repositories the.sig/.ascsidecars are uploaded next to the package.
Exit status is non-zero if any package failed; the remaining packages are still attempted.
SBOM generation
yap 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.3
Captured: name, version, license, runtime/build deps, source URLs and checksums, file hashes, DESCRIBES/DEPENDS_ON relationships.
Advanced usage
Cross-compilation
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.
Multi-package projects
{
"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 .
Build environment preparation
yap prepare # Auto-detect host distro
yap prepare ubuntu-jammy
yap prepare fedora-38
yap prepare --golang arch
yap prepare --skip-sync rocky-9
CI/CD integration
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 week
Examples
The 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 |
PKGBUILD examples
Simple C application
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"; }
Python application
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
}
Web service with systemd
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"
}
Development
Make targets
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 statistics
Testing
Tests 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/...
Internationalization
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.
Troubleshooting
Container runtime
systemctl status docker # or podman
docker run --rm hello-world # test access
sudo usermod -aG docker $USER # fix permissions (re-login required)
Build failures
yap build --verbose
yap zap ubuntu-jammy /path/to/project
yap status
Permission issues
sudo chown -R $USER:$USER artifacts/
setsebool -P container_manage_cgroup true # SELinux (Red Hat family)
Performance
yap build --skip-sync # skip package manager sync
yap build --cleanbuild # clean source before build
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make changes and add tests
- Run
make fmt lint test - Commit and open a pull request
See CODE_OF_CONDUCT.md for community guidelines.
License
GNU General Public License v3.0. See LICENSE.md.
Credits
- Zachary Huff for contributions to Pacur, the project that inspired YAP
- The Arch Linux community for the PKGBUILD format
- All contributors
Built with Go, Cobra, Docker / Podman.
Frequently asked questions
What is YAP — Yet Another Packager?
Build native Linux packages (.deb/.rpm/.apk/.pkg.tar.zst) from a single PKGBUILD via MCP.
How do I install YAP — Yet Another Packager?
It runs on your machine. In Claude Code: claude mcp add yap-yet-another-packager -e 'YAP_VERBOSE=<YAP_VERBOSE>' -- docker run -i --rm ghcr.io/m0rf30/yap-mcp:2.8.0. For other clients, paste the JSON configuration from this page into their MCP settings.
Does YAP — Yet Another Packager need an API key?
Its registry entry lists no required key or secret. Some features may still need an account with the service it connects to.
Is YAP — Yet Another Packager open source?
Yes. Its code is on GitHub under the GPL-3.0 license.
Who maintains YAP — Yet Another Packager?
It is published by M0Rf30. AI.tn lists it but does not maintain or endorse it.
From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.