YAP — Yet Another Packager
Build native Linux packages (.deb/.rpm/.apk/.pkg.tar.zst) from a single PKGBUILD via MCP.
ماذا يمكنك أن تفعل مع 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
التثبيت
أضف هذا إلى إعدادات MCP في عميلك (Claude Desktop: claude_desktop_config.json، وCursor: .cursor/mcp.json، ويستخدم VS Code وغيره الصيغة نفسها «mcpServers»).
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>"
}
}
}
}
متغيرات البيئة
YAP_VERBOSESet to 1 for debug-level JSON-RPC frame logging on stderr.
التوثيق
مأخوذ من ملف README للمشروع على GitHub ويُحدَّث أسبوعيًا. تفتح الروابط على GitHub.
المحتويات
- 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.
الأسئلة الشائعة
ما هو YAP — Yet Another Packager؟
Build native Linux packages (.deb/.rpm/.apk/.pkg.tar.zst) from a single PKGBUILD via MCP.
كيف أثبّت YAP — Yet Another Packager؟
يعمل على جهازك. في 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. وفي العملاء الآخرين، الصق إعداد JSON من هذه الصفحة في إعدادات MCP الخاصة بهم.
هل يحتاج YAP — Yet Another Packager إلى مفتاح API؟
لا يذكر إدراجه في السجل أي مفتاح أو سر إلزامي. قد تتطلب بعض الميزات حسابًا لدى الخدمة التي يتصل بها.
هل YAP — Yet Another Packager مفتوح المصدر؟
نعم. شيفرته متاحة على GitHub بترخيص GPL-3.0.
من يصون YAP — Yet Another Packager؟
ينشره M0Rf30. يدرجه AI.tn لكنه لا يصونه ولا يوصي به.
من سجل MCP الرسمي. الإدراج ليس توصية: راجع شيفرة الخادم وصلاحياته قبل منحه الوصول إلى بياناتك.