# PkgForge

Package Forge

## About

[PkgForge](https://github.com/pkgforge) provides portable packages and static binaries for Linux, along with [Soar](https://github.com/pkgforge/soar) - a fast package manager written in Rust.

## Quick Start

```bash
# Install Soar
curl -fsSL "https://soar.qaidvoid.dev/install.sh" | sh

# Install a package
soar install pkg_name
```

## Resources

* [Soar Documentation](/soar/readme)
* [Package Formats](/formats/packages)
* [SBUILD Specification](/sbuild/introduction)
* [Package Search](https://pkgs.pkgforge.dev/)


# About

{% embed url="<https://soar.pkgforge.dev/gif?tmp.T8cejqbouL=tmp.zCz9xm0XHw>" %}

[PkgForge](https://github.com/pkgforge) provides portable packages, static binaries, and [Soar](https://github.com/pkgforge/soar) - a package manager written in Rust.


# PkgForge-Community

Community Organization

[PkgForge-Community](https://github.com/pkgforge-community) is a sub-organization that maintains [forks](https://github.com/orgs/pkgforge-community/repositories?q=fork%3Atrue+archived%3Afalse) of packages and dependencies used by PkgForge.

These forks preserve complete commit and release history for security and transparency.


# PkgForge-Dev

Development Organization

[PkgForge-Dev](https://github.com/pkgforge-dev) hosts development and experimental projects.

## Projects

* [Anylinux-AppImages](/orgs/pkgforge-dev/anylinux-appimages) - Portable AppImages for any Linux distro


# Anylinux-AppImages

Portable AppImages

[Anylinux-AppImages](https://github.com/pkgforge-dev/anylinux-appimages) builds AppImages that work on any Linux distribution.

## Features

* Uses static runtime for maximum compatibility
* Works on both glibc and musl systems
* Type-3 AppImages (no FUSE required)
* Automated builds via GitHub Actions

## Repository

[github.com/pkgforge-dev/anylinux-appimages](https://github.com/pkgforge-dev/anylinux-appimages)


# Soar

Soar Package Manager

[Soar](https://github.com/pkgforge/soar) is a fast package manager written in Rust for installing portable packages and static binaries on Linux.

## Installation

```bash
curl -fsSL "https://soar.qaidvoid.dev/install.sh" | sh
```

## Usage

```bash
soar install package_name    # Install a package
soar search query            # Search packages
soar update                  # Update packages
soar remove package_name     # Remove a package
soar log package_name        # View build log
```

## Features

* **No dependencies**: Single static binary
* **No sudo required**: Installs to user directory
* **Portable packages**: Works across Linux distributions
* **Prebuilt cache**: No compilation needed

## Documentation

* [Packages](/soar/readme/packages) - Supported package types
* [Security](/soar/readme/security) - Security model


# Packages

Package Ecosystem

## Supported Platforms

* `x86_64-Linux`
* `aarch64-Linux`

## Package Types

Soar supports:

* [Static binaries](/formats/binaries/static) - CLI tools
* [AppImages](/formats/packages/appimage) - Portable GUI apps
* [Other portable formats](/formats/packages) - AppBundles, FlatImages, RunImages, etc.

## Features

* **Portable**: Packages work across Linux distributions
* **Standalone**: Download and use packages without Soar
* **Prebuilt cache**: No compilation required


# Security

Security Model

## Build Security

* **Unprivileged**: No sudo/doas required
* **Isolated builds**: CI runs in rootless containers
* **Transparent logs**: View build logs with `soar log $pkg`

## Verification

* **Checksums**: b3sum + sha256sum
* **Attestations**: [GitHub Artifact Attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations)
* **Signing**: minisign signatures

Soar's build process meets [SLSA Build L2](https://slsa.dev/spec/v1.0/levels#build-l2).


# Binaries

Binary Types

Binary types for CLI applications:

* [Static](/formats/binaries/static) - Statically linked binaries (no dependencies)
* [Dynamic](/formats/binaries/dynamic) - Dynamically linked binaries


# Static

Statically Linked Binaries (.pkg\_type == static)

{% hint style="success" %} <mark style="color:orange;">**Build Profile**</mark>

* [x] Prefer [**`mimalloc`**](https://github.com/microsoft/mimalloc) over other musl allocators ([<mark style="color:red;">**Not Always**</mark>](#user-content-fn-1)[^1])
* [x] Prefer [LTO](https://gcc.gnu.org/wiki/LinkTimeOptimization)
* [x] Prefer [PIE](https://en.wikipedia.org/wiki/Position-independent_code)
  {% endhint %}

{% hint style="success" %} <mark style="color:purple;">**Sources**</mark>

* Most (around 90%) of our **`static`** packages are built from source using standard build tools.
* The rest are fetched from upstream like GitHub Releases etc.
  {% endhint %}

{% hint style="warning" %} <mark style="color:orange;">**`Nomenclature`**</mark>

* **`*source*`** : Implies it was built from source

* **`*official*`** : Implies it was built/fetched from official source

* **`*stable*`** : Implies it was likely fetched from upstream source & not built from source
  {% endhint %}

* [x] If the binary is a desktop app i.e. needs desktop integration, it needs to go under [**./packages**](https://github.com/pkgforge/soarpkgs/tree/main/packages)

[^1]: We have had reports of users running into segfault errors on old hardware


# Dynamic

Dynamically Linked Binaries

{% hint style="warning" %}

* This is only for testing & **Portable Static Binaries should Always be preferred**
* As such we likely have almost no dynamic binaries in our repo, so this section is intentionally empty
* Please check the [Static](/formats/binaries/static) section instead
  {% endhint %}


# Packages

Supported Package Formats

Portable package formats for GUI applications:

* [AppImage](/formats/packages/appimage) - Single-file portable applications
* [AppBundle](/formats/packages/appbundle) - Portable app bundles
* [FlatImage](/formats/packages/flatimage) - Flatpak-based portable images
* [RunImage](/formats/packages/runimage) - Container-based portable apps
* [NixAppImage](/formats/packages/nixappimage) - Nix-based AppImages
* [Archive](/formats/packages/archive) - Compressed archives

## Troubleshooting

See [Errors & Quirks](/formats/packages/errors-and-quirks) for common issues (FUSE, fonts, namespaces).


# AppImage

https\://en.wikipedia.org/wiki/AppImage

{% hint style="info" %} <mark style="color:purple;">**Sources**</mark>

* Upstream prebuilt if it exists & is actively maintained
* Community created prebuilts if official prebuilt doesn't exist & we can't build from source
  {% endhint %}

### Schema

{% hint style="info" %}
[<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg): <mark style="color:orange;">**`${PKG_NAME}`**</mark>

[<mark style="color:purple;">**`.pkg_type`**</mark>](/sbuild/specification/2.pkg): <mark style="color:green;">**`appimage`**</mark>

<mark style="color:blue;">**`${SBUILD_PKG}`**</mark> : <mark style="color:green;">**`${PKG_NAME}.appimage`**</mark>
{% endhint %}

***

### **Prerequisites (`HOST)`**

{% hint style="info" %}

* [**Fuse**](broken://pages/8hHKbF95BBtvZUMBe4k9): Required for mounting Filesystems & Images (Can still be run with [<mark style="color:orange;">`--appimage-extract-and-run`</mark> | <mark style="color:orange;">`APPIMAGE_EXTRACT_AND_RUN=1`</mark>](https://docs.appimage.org/user-guide/troubleshooting/fuse.html#fallback-if-fuse-can-t-be-made-working))
* [**Fonts**](broken://pages/1Jy4S9xshgEUK6bIc0fl): Required to display/render Non-English Chars, Emojis, Symbols etc.
* [<mark style="color:blue;">**Kernel User NameSpaces**</mark>](broken://pages/tjmP70tpwiHVQQutUXFd): Required for Sandboxing, Security & Performance
  {% endhint %}

***

### Sandbox

{% hint style="danger" %}

* AppImages have no built-in sandboxing
* There exists third party tools like [<mark style="color:blue;">**aisap**</mark>](https://github.com/mgord9518/aisap) , but we <mark style="color:red;">**DO NOT RECOMMEND**</mark> it as it is not actively maintained
  {% endhint %}

***

### Quirks

{% hint style="info" %} <mark style="color:red;">**WARNINGS**</mark>

* NEVER run **`strip`**, **`objcopy`** or any other binary rewriting tool as they will often just strip the **`squashfs|dwarfs`** archive, only preserving the **`runtime`**.
* A typical <mark style="color:green;">**`.appimage`**</mark> file is not a real elf binary, thus will not survive this process.
* On [<mark style="color:purple;">**NixOS**</mark>](https://nixos.org/), you will need to follow: <https://wiki.nixos.org/wiki/Appimage>
  {% endhint %}


# AppBundle

https\://github.com/xplshn/AppBundleHUB

* **Author**: [`@xplshn`](https://github.com/xplshn)
* **Project Page**: <https://github.com/xplshn/pelf/>
* **Sources**: Mostly prebuilts from <https://github.com/xplshn/AppBundleHUB>

***

### Schema

{% hint style="info" %}
[<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg): <mark style="color:orange;">**`${PKG_NAME}`**</mark>

[<mark style="color:purple;">**`.pkg_type`**</mark>](/sbuild/specification/2.pkg): <mark style="color:green;">**`appbundle`**</mark>

<mark style="color:blue;">**`${SBUILD_PKG}`**</mark> : <mark style="color:green;">**`${PKG_NAME}.appbundle`**</mark>
{% endhint %}

***

### **Prerequisites (`HOST)`**

{% hint style="info" %}

* [**Fuse**](broken://pages/8hHKbF95BBtvZUMBe4k9): Required for mounting Filesystems & Images
* [**Fonts**](broken://pages/1Jy4S9xshgEUK6bIc0fl): Required to display/render Non-English Chars, Emojis, Symbols etc.
* [<mark style="color:blue;">**Kernel User NameSpaces**</mark>](broken://pages/tjmP70tpwiHVQQutUXFd): Required for Sandboxing, Security & Performance
  {% endhint %}

***

### Quirks

{% hint style="info" %} <mark style="color:red;">**WARNINGS**</mark>

* NEVER run **`strip`**, **`objcopy`** or any other binary rewriting tool as they will often just strip the **`squashfs|dwarfs`** archive, only preserving the **`runtime`**.
* A typical <mark style="color:green;">**`.appbundle`**</mark> file is not a real elf binary, thus will not survive this process.
  {% endhint %}


# FlatImage

A hybrid of Flatpak sandboxing with AppImage portability

* Author: [`@ruanformigoni`](https://github.com/ruanformigoni)
* Project Page: <https://github.com/ruanformigoni/flatimage>
* Detailed Docs: <https://flatimage.github.io/docs/>

***

### Schema

{% hint style="info" %}
[<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg): <mark style="color:orange;">**`${PKG_NAME}-${BASE_DISTRO_IMAGE}`**</mark>

[<mark style="color:purple;">**`.pkg_type`**</mark>](/sbuild/specification/2.pkg): <mark style="color:green;">**`flatimage`**</mark>

<mark style="color:blue;">**`${SBUILD_PKG}`**</mark> : <mark style="color:green;">**`${PKG_NAME}-${BASE_DISTRO_IMAGE}.flatimage`**</mark>

{% code overflow="wrap" %}

```bash
!#Examples
firefox-alpine.FlatImage --> Created using alpine as base BaseImage/RootFS
steam-cachyos.FlatImage --> Created using CachyOs as BaseImage/RootFS
librewolf-alpine-nix.FlatImage --> Created using alpine as BaseImage/RootFS with Nix on top of it
```

{% endcode %}
{% endhint %}

***

### **Prerequisites (`HOST)`**

{% hint style="info" %}

* [**Fuse**](broken://pages/8hHKbF95BBtvZUMBe4k9): Required for mounting Filesystems & Images
* [**Fonts**](broken://pages/1Jy4S9xshgEUK6bIc0fl): Required to display/render Non-English Chars, Emojis, Symbols etc.
* [<mark style="color:blue;">**Kernel User NameSpaces**</mark>](broken://pages/tjmP70tpwiHVQQutUXFd): Required for Sandboxing, Security & Performance
  {% endhint %}

***

### Sandbox

{% hint style="success" %}
FlatImages have built-in sandboxing, check docs: <https://flatimage.github.io/docs/cmd/perms/>
{% endhint %}

***

### Quirks

{% hint style="info" %} <mark style="color:red;">**WARNINGS**</mark>

* NEVER run **`strip`**, **`objcopy`** or any other binary rewriting tool as they will often just strip the **`squashfs|dwarfs`** archive, only preserving the **`runtime`**.
* A typical <mark style="color:green;">**`.flatimage`**</mark> file is not a real elf binary, thus will not survive this process.
  {% endhint %}


# RunImage

Portable single-file Linux container, Similar to FlatImage

* **Author**: [`@VHSgunzo`](https://github.com/VHSgunzo)
* **Project Page**: <https://github.com/VHSgunzo/runimage>
* **Sources**: A [base runimage](https://github.com/pkgforge-dev/runimage-base) is used to install packages using a distro & then rebuilt/packaged

***

### Schema

{% hint style="info" %}
[<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg): <mark style="color:orange;">**`${PKG_NAME}`**</mark>

[<mark style="color:purple;">**`.pkg_type`**</mark>](/sbuild/specification/2.pkg): <mark style="color:green;">**`runimage`**</mark>

<mark style="color:blue;">**`${SBUILD_PKG}`**</mark> : <mark style="color:green;">**`${PKG_NAME}.runimage`**</mark>
{% endhint %}

***

### **Prerequisites (`HOST)`**

{% hint style="info" %}

* [**Fuse**](broken://pages/8hHKbF95BBtvZUMBe4k9): Required for mounting Filesystems & Images (Can still be run with `--runtime-extract-and-run | RUNTIME_EXTRACT_AND_RUN=1` )
* [**Fonts**](broken://pages/1Jy4S9xshgEUK6bIc0fl): Required to display/render Non-English Chars, Emojis, Symbols etc.
* [<mark style="color:blue;">**Kernel User NameSpaces**</mark>](broken://pages/tjmP70tpwiHVQQutUXFd): Required for Sandboxing, Security & Performance
  {% endhint %}

***

### Sandbox

{% hint style="success" %}
RunImages have built-in sandboxing, check the docs: <https://github.com/VHSgunzo/runimage#usage>
{% endhint %}

***

### Quirks

{% hint style="info" %} <mark style="color:red;">**WARNINGS**</mark>

* NEVER run **`strip`**, **`objcopy`** or any other binary rewriting tool as they will often just strip the **`squashfs|dwarfs`** archive, only preserving the **`runtime`**.
* A typical <mark style="color:green;">**`.runimage`**</mark> file is not a real elf binary, thus will not survive this process.
  {% endhint %}


# NixAppImage

AppImages created from NixOs Derivations & FHS

* **Author**: [`@ralismark`](https://github.com/ralismark) `+` [`@Azathothas`](https://github.com/Azathothas) `+` [`Others`](https://github.com/NixOS/bundlers)
* **Project Page**: <https://github.com/pkgforge/nix-appimage>
* Described as An AppImage created using a [Nix-Bundler](https://github.com/NixOS/bundlers) like [pkgforge/nix-appimage](https://github.com/pkgforge/nix-appimage) & [DavHau/nix-portable](https://github.com/DavHau/nix-portable)
* **Sources**: [NixOS Packages](https://github.com/NixOS/nixpkgs)

***

### Schema

{% hint style="info" %}
[<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg): <mark style="color:orange;">**`${PKG_NAME}`**</mark>

[<mark style="color:purple;">**`.pkg_type`**</mark>](/sbuild/specification/2.pkg): <mark style="color:green;">**`nixappimage`**</mark>

<mark style="color:blue;">**`${SBUILD_PKG}`**</mark> : <mark style="color:green;">**`${PKG_NAME}.nixappimage`**</mark>
{% endhint %}

***

### **Prerequisites (`HOST)`**

{% hint style="info" %}

* [**Fuse**](broken://pages/8hHKbF95BBtvZUMBe4k9): Required for mounting Filesystems & Images
* [**Fonts**](broken://pages/1Jy4S9xshgEUK6bIc0fl): Required to display/render Non-English Chars, Emojis, Symbols etc.
* [<mark style="color:blue;">**Kernel User NameSpaces**</mark>](broken://pages/tjmP70tpwiHVQQutUXFd): Required for Sandboxing, Security & Performance
  {% endhint %}

***

### Sandbox

{% hint style="success" %}
NixAppImages have built-in sandboxing, run **`SHOW_HELP=1`** to see available options.
{% endhint %}

***

### Quirks

{% hint style="info" %} <mark style="color:red;">**KNOWN ISSUES**</mark>

* **LibGL**: <https://github.com/NixOS/nixpkgs/issues/9415>
* **Size**: About **`2-5x`** larger than other formats, but **guarantee absolute portability**.

<mark style="color:red;">**WARNINGS**</mark>

* NEVER run **`strip`**, **`objcopy`** or any other binary rewriting tool as they will often just strip the **`squashfs|dwarfs`** archive, only preserving the **`runtime`**.
* A typical <mark style="color:green;">**`.nixappimage`**</mark> file is not a real elf binary, thus will not survive this process.
  {% endhint %}


# Archive

Usually extract & run (or even Self Extractable) archives provided by official sources themselves.

{% hint style="success" %} <mark style="color:orange;">**Build Profile**</mark>

* [x] Repackage with [wrappe](https://github.com/Systemcluster/wrappe) if upstream source is already portable
* [x] Repackage with [sharun](https://github.com/VHSgunzo/sharun) + [wrappe](https://github.com/Systemcluster/wrappe)/[uruntime](https://github.com/VHSgunzo/uruntime) if upstream source is not portable
  {% endhint %}

{% hint style="success" %} <mark style="color:purple;">**Sources**</mark>

* Upstream source if they release a portable archive
* Distro Package or Registries like npm, pypi etc if prebuilt upstream doesn't exist
  {% endhint %}

{% hint style="warning" %}
**`Nomenclature`**

* **`*sharun*`** : Implies it was packaged with [**sharun**](https://github.com/VHSgunzo/sharun)
* **`*wrappe*`** : Implies it was packaged with [**wrappe**](https://github.com/Systemcluster/wrappe)
* **`*source*`** : Implies it was build from source & then packaged
* **`*stable*`** : Implies a prebuilt was fetched & then packages
* **`*npm*`** : Implies it was packaged from a [**npm**](https://www.npmjs.com/) package
* **`*pypi*`** : Implies it was packaged from a [**pypi**](https://pypi.org/) package
  {% endhint %}


# Errors & Quirks

Common Issues with Portable Packages

Common issues when running portable packages:

* [**Fuse**](/formats/packages/errors-and-quirks/fuse): Required for mounting Filesystems & Images
* [**Fonts**](/formats/packages/errors-and-quirks/fonts): Required to display/render Non-English Chars, Emojis, Symbols etc.
* [**Kernel User NameSpaces**](/formats/packages/errors-and-quirks/namespaces): Required for Sandboxing, Security & Performance


# FUSE

Required for mounting Filesystems & Images

{% hint style="info" %}
Required for mounting Filesystems & Images

Can still be run with `--appimage-extract-and-run` | `APPIMAGE_EXTRACT_AND_RUN=1`
{% endhint %}

AppImages and similar formats use FUSE (Filesystem in Userspace) to mount themselves.

## Common Errors

```
fusermount: mount failed: Operation not permitted
```

```
Cannot mount AppImage, please check your FUSE setup
```

## Solutions

### Install FUSE

**Debian/Ubuntu:**

```bash
sudo apt install fuse libfuse2
```

**Fedora:**

```bash
sudo dnf install fuse fuse-libs
```

**Arch:**

```bash
sudo pacman -S fuse2
```

### Extract Instead

Most AppImages support extraction as fallback:

```bash
./app.AppImage --appimage-extract-and-run
```

Or set the environment variable:

```bash
APPIMAGE_EXTRACT_AND_RUN=1 ./app.AppImage
```

Manual extraction:

```bash
./app.AppImage --appimage-extract
./squashfs-root/AppRun
```

### Use Type-3 AppImages

Type-3 AppImages don't require FUSE - they use `squashfuse` embedded in the runtime.


# Fonts

Required to display/render Non-English Chars, Emojis, Symbols etc.

{% hint style="info" %}
Required to display/render Non-English Chars, Emojis, Symbols etc.
{% endhint %}

Portable packages may have font rendering issues due to missing fonts or fontconfig.

## Common Issues

* Missing fonts (squares or boxes instead of characters)
* Wrong font fallbacks
* CJK characters not rendering
* Emojis showing as boxes

## Solutions

### Install Common Fonts

**Debian/Ubuntu:**

```bash
sudo apt install fonts-noto fonts-liberation fonts-noto-color-emoji
```

**Fedora:**

```bash
sudo dnf install google-noto-fonts-common liberation-fonts google-noto-emoji-fonts
```

**Arch:**

```bash
sudo pacman -S noto-fonts noto-fonts-emoji ttf-liberation
```

### Set Font Environment

```bash
export FONTCONFIG_PATH=/etc/fonts
```


# Namespaces

Required for Sandboxing, Security & Performance

{% hint style="info" %}
Required for Sandboxing, Security & Performance
{% endhint %}

Some portable packages use user namespaces for sandboxing, which may be restricted on certain systems.

## Common Errors

```
clone failed: Operation not permitted
```

```
user namespaces are not enabled
```

## Solutions

### Enable User Namespaces

**Check current setting:**

```bash
sysctl kernel.unprivileged_userns_clone
```

**Enable temporarily:**

```bash
sudo sysctl -w kernel.unprivileged_userns_clone=1
```

**Enable permanently:**

```bash
echo 'kernel.unprivileged_userns_clone=1' | sudo tee /etc/sysctl.d/userns.conf
sudo sysctl --system
```

### Debian/Ubuntu Specific

```bash
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
```

### Use --no-sandbox

Some applications accept `--no-sandbox` flag (use with caution).


# Introduction

A quick intro to SBUILD

SBUILD is a YAML-based build script format inspired by APKBUILD and PKGBUILD.

## Getting Started

1. Read the [Specification](/sbuild/specification)
2. View [Examples](/sbuild/instructions/examples)
3. Browse [existing packages](https://github.com/pkgforge/soarpkgs/tree/main/packages)
4. [Write your own](/sbuild/instructions)


# Specification

The Official Specification for SBUILD

1. [**Prerequisite**](/sbuild/specification/0.prerequisite) **(Start Here)**
2. [**Shebang**](/sbuild/specification/1.shebang) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
3. [**Package**](/sbuild/specification/2.pkg) (**TYPE**: <mark style="color:red;">**ENFORCED**</mark>)
4. [**Version**](/sbuild/specification/3.version) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
5. [**Application ID**](/sbuild/specification/4.appid) (**TYPE:** <mark style="color:green;">**`RECOMMENDED`**</mark>)
6. [**Build Assets**](/sbuild/specification/5.buildasset) (**TYPE:** <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
7. [**Build Tools**](/sbuild/specification/6.buildutil) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
8. [**Category**](/sbuild/specification/7.category) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
9. [**Description**](/sbuild/specification/8.description) (**TYPE**: <mark style="color:red;">**ENFORCED**</mark>)
10. [**Desktop**](/sbuild/specification/9.desktop) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
11. [**GHCR Package**](https://github.com/pkgforge/docs/blob/main/sbuild/specification/10.ghcrpkg.md) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
12. [**HomePage**](/sbuild/specification/11.homepage) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
13. [**Icon**](/sbuild/specification/12.icon) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
14. [**License**](/sbuild/specification/13.license) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
15. [**Maintainer**](/sbuild/specification/14.maintainer) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
16. [**Note**](/sbuild/specification/15.note) (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
17. [**Provides**](/sbuild/specification/16.provides) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
18. [**Repology**](/sbuild/specification/17.repology) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
19. [**Source URL**](/sbuild/specification/18.sourceurl) (**TYPE**: <mark style="color:red;">**ENFORCED**</mark>)
20. [**Tag**](/sbuild/specification/19.tag) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
21. [**x\_exec**](/sbuild/specification/20.x_exec) (**TYPE**: <mark style="color:red;">**ENFORCED**</mark>)


# 0.Prerequisite

## Tools

* **Linter**: Validates SBUILD scripts
* **Runner**: Executes validated SBUILD scripts
* **SBUILDER**: Combined linter + runner (used by `soar build`)

## Field Types

* <mark style="color:red;">**`ENFORCED`**</mark>: Required field
* <mark style="color:blue;">**`NON_ENFORCED`**</mark>: Optional field
* <mark style="color:green;">**`RECOMMENDED`**</mark>: Optional but encouraged

## Directories

* `$SBUILD_OUTDIR`: Working directory for the build
* `$SBUILD_TMPDIR`: Temp directory inside SBUILD\_OUTDIR (`$SBUILD_OUTDIR/SBUILD_TEMP`)

## Script Blocks

* `x_exec.pkgver`: Shell commands to fetch version
* `x_exec.run`: Shell commands to build/download the package

{% hint style="info" %}
Validate your SBUILD with [yamllint](https://www.yamllint.com/) and `x_exec.run` with [shellcheck](https://www.shellcheck.net/).
{% endhint %}


# 1.Shebang

\#!/SBUILD

```yaml
#!/SBUILD ver @v1.0.0
_disabled: false
_rolling: false
```

## Fields

### `#!/SBUILD ver @${VERSION}`

Version assertion for the linter/runner. (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)

### `_disabled`

Disable the script. (**TYPE**: <mark style="color:red;">**`ENFORCED`**</mark>)

* `false` - Script is enabled (default)
* `true` - Script is disabled

When disabled, specify a reason:

```yaml
_disabled: true
_disabled_reason:
  abandoned:
    - date: "2024-12-31"
      reason: "No longer maintained"
```

Reason types: `abandoned`, `broken`, `deprecated`, `dmca`, `insecure`, `replaced`

### `_rolling`

Mark as rolling release for periodic rebuilds. (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)

```yaml
_rolling: true
x_exec:
  pkgver: |
    echo "nightly-$(date +%Y%m%d)"
```

Used for packages without versioned releases (nightly builds, git HEAD, etc.).


# 2.Pkg

The type of Package or Binary

{% code overflow="wrap" %}

```yaml
#Example ONLY
pkg: "Real Name, It will be Installed & Integrated based on this Value"
pkg_id: "Unique Identifier, Based on src_url, used for identifying this .pkg"
pkg_type: "Pkg Format, if empty or nonexistent, Builder reads Magic Bytes to determine format"
```

{% endcode %}

* [x] <mark style="color:purple;">**`pkg`**</mark> is the **Canonical** name of the Package. *It will be installed as this, regardless of the actual filename*. Desktop entry will also show this name (**TYPE**: <mark style="color:red;">**ENFORCED**</mark>)
* [x] [<mark style="color:purple;">**`pkg_id`**</mark>](#user-content-fn-1)[^1] is like an **`ID`**, It is **`Unique` & `NOT SHARED`** with any other <mark style="color:purple;">**`pkg_id`**</mark> from other packages (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)

> - <mark style="color:purple;">**`pkg_id`**</mark> is to make it seamless to add multiple binaries from multiple sources for the same pkg
>
> - <mark style="color:purple;">**`pkg_id`**</mark> is just <mark style="color:purple;">**`src_url`**</mark> without <mark style="color:orange;">`http|https`</mark> schema along with some extra params
>
> - Example: <mark style="color:purple;">**`src_url`**</mark>` `` ``= ` "<mark style="color:blue;">`https://`</mark><mark style="color:orange;">`github.com`</mark><mark style="color:blue;">`/`</mark><mark style="color:yellow;">`AppImager`</mark><mark style="color:blue;">`/`</mark><mark style="color:green;">`example-appimage`</mark>" --> <mark style="color:orange;">**`github.com`**</mark><mark style="color:blue;">**`.`**</mark><mark style="color:yellow;">**`AppImager`**</mark><mark style="color:blue;">**`.`**</mark><mark style="color:green;">**`example-appimage`**</mark>
>
> - Notice how, all special chars like `/` --> `.` and `http://|https://` was removed Another example, where the repo has multiple appimages:
>
> > * **`alpha`** --> github.com.AppImager.example-appimag&#x65;**.alpha**
> > * **`latest`** --> github.com.AppImager.example-appimage.**latest**
> > * **`nightly`** --> github.com.AppImager.example-appimag&#x65;**.nightly**
> > * **`stable`** --> github.com.AppImager.example-appimag&#x65;**.stable**
>
> * It's just **`$tag`** or some other identifier added at last

{% hint style="info" %}
**If you don't specify a `pkg_id`**, the first entry of <mark style="color:purple;">**`src_url`**</mark> is auto converted & added as <mark style="color:purple;">**`pkg_id`**</mark>
{% endhint %}

* [x] <mark style="color:purple;">**`pkg_type`**</mark> is the Package Format, it can be one of the following (<mark style="color:orange;">**`lowercase`**</mark>) (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)

> - [**AppImage**](/formats/packages/appimage) denotes it is an [AppImage](https://appimage.org/) <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**appimage**</mark>**"**
> - [**AppBundle**](/formats/packages/appbundle) denotes it is an [AppBundle](https://github.com/xplshn/pelf/) <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**appbundle**</mark>**"**
> - [**Archive**](/formats/packages/archive) denotes it is an archive (**SELF-EXTRACTABLE**) format: <mark style="color:purple;">`.7z .bz .bz2 .gz .lz4 .lzma .rar .sz .tar .xz .zst`</mark> or a mix-mash of these. This includes formats like [alpix](https://github.com/QaidVoid/alpix), [staticx](https://github.com/JonathonReinhart/staticx) etc. <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**archive**</mark>**"**
> - [**Dynamic**](/formats/binaries/dynamic) denotes it is a *Dynamic Binary* <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**dynamic**</mark>**"**
> - [**FlatImage**](/formats/packages/flatimage) denotes it is a [*FlatImage*](https://github.com/ruanformigoni/flatimage) , <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**flatimage**</mark>**"**
> - [**GameImage**](broken://pages/QbbRr9n5JK9oqWInlJrL) denotes it is a [*GameImage*](https://github.com/ruanformigoni/gameimage) , <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**gameimage**</mark>**"**
> - [**NixAppImage**](/formats/packages/nixappimage) denotes it is a [*NixAppImage*](https://github.com/ralismark/nix-appimage) , <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**nixappimage**</mark>**"**
> - [**RunImage** ](/formats/packages/runimage)denotes it is a [*RunImage*](https://github.com/VHSgunzo/runimage) , <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**runimage**</mark>**"**
> - [**Static**](/formats/binaries/static) denotes it is a *Static Binary* , <mark style="color:purple;">**pkg\_type**</mark>**: "**<mark style="color:orange;">**static**</mark>**"**

{% hint style="info" %}
**`Runner/Linter`** will *read the magic bytes* to determine correct format in case this field is empty.
{% endhint %}

[^1]: `pkg_id` will be *auto generated* based on `src_url` **if `pkg_id` is empty**


# 3.Version

Package Version (TYPE: RECOMMENDED)

## Fixed Version

```yaml
pkgver: "1.2.3"
```

Set a fixed version. `x_exec.pkgver` is still used to check for updates.

## Dynamic Version

Omit `pkgver` to always fetch from `x_exec.pkgver`:

```yaml
x_exec:
  pkgver: |
    curl -qfsSL "https://api.github.com/repos/owner/repo/releases/latest" | jq -r '.tag_name'
```

## Rolling Builds

For packages without versioned releases (nightly, git HEAD, etc.):

```yaml
_rolling: true
x_exec:
  pkgver: |
    echo "nightly-$(date +%Y%m%d)"
```

`_rolling: true` marks the package for periodic rebuilds regardless of version changes.


# 4.AppID

AppStream App ID (TYPE: RECOMMENDED)

```yaml
#Example ONLY
app_id: "Appstream App Id, flatpak's scheme preferred, otherwise can be empty"
```

* [x] <mark style="color:purple;">**`app_id`**</mark> is [AppStream App Id](https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html#tag-id-generic). (**TYPE:**<mark style="color:green;">**`RECOMMENDED`**</mark>)
* [x] You can find the <mark style="color:purple;">**`app_id`**</mark> by searching it on [Flathub](https://flathub.org/)

<figure><img src="/files/0IxIV5gJtk8CacLCQSTB" alt=""><figcaption><p>Finding <code>app_id</code> of FireFox on <a href="https://flathub.org/">FlatHub</a></p></figcaption></figure>

* [x] You can also find it in [**Appstream**](https://www.freedesktop.org/software/appstream/docs/) **`Appdata.xml`** or **`Metainfo.xml`** files

<figure><img src="/files/BBeFEeR7wOOMCU5uCcDl" alt=""><figcaption><p>Finding <code>app_id</code> from AppStream</p></figcaption></figure>

{% hint style="info" %}

* Sometimes, this id can also be found in **`.Desktop`** file.

* **If you can't find the** <mark style="color:purple;">**`app_id`**</mark> at all, Just **DO NOT USE IT** or **JUST LEAVE EMPTY**
  {% endhint %}

* [x] <mark style="color:purple;">**`app_id`**</mark> is **USED FOR DESKTOP INTEGRATION**

{% hint style="info" %}
This is **NOT TO BE CONFUSED** with <mark style="color:purple;">**`pkg_id`**</mark>, <mark style="color:purple;">**`pkg_id`**</mark> **is to identify the pkg**, it is **NOT FOR DESKTOP Integration**
{% endhint %}


# 5.BuildAsset

Extra Assets/Files Needed during Build (TYPE: NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
#All of the files will be downloaded & added to "${SBUILD_OUTDIR/SBUILD_TEMP}" (Also Known as $SBUILD_TMPDIR prior to running the x_exec part
build_asset:
  - url: "https://example.com/fileA.tar" #Downloaded
    out: "example_01.tar" #Saved as $SBUILD_OUTDIR/SBUILD_TEMP/example_01.tar
  - url: "https://example.com/abc.gif" #Downloaded
    out: "xyz.gif" #Saved as $SBUILD_OUTDIR/SBUILD_TEMP/xyz.gif
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE:**<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] This can be used to pull in Static Assets needed for <mark style="color:purple;">**`x_exec.run`**</mark> part.
* [x] Accessible using <mark style="color:orange;">**`${SBUILD_TMPDIR}/$FILE`**</mark> OR <mark style="color:orange;">**`$SBUILD_OUTDIR/SBUILD_TEMP/$FILE`**</mark> [<mark style="color:green;">**`ENV VARS`**</mark>](/sbuild/instructions/env_vars-x_exec.run)
* [x] The benefit of using this over doing it manually in <mark style="color:purple;">**`x_exec.run`**</mark> is that it's parallelized & pre-downloaded
* [x] Can have single or multiple entries


# 6.BuildUtil

Additional Utilities (Programs) that should be Installed prior to BUILD (TYPE:NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
#WARNING: DO NOT USE THIS TO INSTALL STUFF LIKE GIT as that is known not to work as static binary
#This should only be used for static bins, (use build_dep instead CURRENTLY NOT IMPLEMENTED)
#soar will add these using soar dl temporarily in cache prior to running the x_exec part
#if these are already installed/cached by soar, soar will skip them (Unless Upgrade is found)
build_util:
  - "curl" #for web stuff
  - "jq" #for parsing json
  - "ouch" #to extract archives easily without remembering flags
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] This can be used to pull in [**`Static Binaries`**](/formats/binaries/static) if some extra tools are being used

{% hint style="info" %}
**Use this only if your distro doesn't provide it**, or **you need the latest version of a tool**
{% endhint %}

* [x] Can have single or multiple entries


# 7.Category

Official Free Desktop Spec Categories (TYPE:RECOMMENDED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
category:
  - "Core"
  - "Utility"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:green;">**`RECOMMENDED`**</mark>)
* [x] If it is used, it MUST be one of the Registered Categories as per the [**FreeDesktop Spec**](https://specifications.freedesktop.org/menu-spec/latest/category-registry.html)

> - [**Main Categories**](https://specifications.freedesktop.org/menu-spec/latest/category-registry.html)
> - [**Additional Categories**](https://specifications.freedesktop.org/menu-spec/latest/additional-category-registry.html)

* [x] It can contain multiple entries

{% hint style="info" %}
**If it is left empty or doesn't exist, It is set to** <mark style="color:orange;">**`Utility`**</mark> **by default**
{% endhint %}


# 8.Description

A short summary about the Package

{% code overflow="wrap" %}

```yaml
#Example ONLY
description: "A short summary about the pkg"
```

{% endcode %}

* [x] Short Summarized <mark style="color:orange;">**Description**</mark> about the <mark style="color:purple;">**`$pkg`**</mark> (**TYPE**:<mark style="color:red;">**`ENFORCED`**</mark>)
* [x] [**repology-fetcher** ](https://github.com/pkgforge/metadata/blob/main/soarpkgs/scripts/repology_fetcher.sh)can Autogenerate Multiple Description from [**Repology**](https://repology.org/projects/), Pick the Best one.
* [x] [**search.nixos.org**](https://search.nixos.org/packages) also has Saner Descriptions
* [x] Otherwise, Use abridged version from the <mark style="color:purple;">**`$pkg`**</mark>'s <mark style="color:orange;">**Homepage**</mark> etc

{% hint style="info" %}
For [<mark style="color:purple;">**SBUILD**</mark>](https://github.com/pkgforge/soarpkgs) that [**provides multiple progs**](/sbuild/specification/16.provides), you can have a per prog description:

{% code overflow="wrap" %}

```yaml
description:
  _default: "A simple description that would apply for the entire .pkg_family" #Applies to the whole pkg_family, overriden if seprate description for each prog exist (Like Below)
  progA: "A simple description only for progA" #Only Applies to progA
  progB: "Another description for progB" #Only Applies to progB
```

{% endcode %}
{% endhint %}


# 9.Desktop

Fetch .Desktop file from Remote/Local (SBUILD) Source (TYPE: NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
desktop:
 #Can contain one of (or all of): url, file, dir
 #If it contains multiple (or all), the builder WILL STOP UPON FIRST successful desktop file MATCH
  url: "#A Direct RAW URL to download a .desktop file"
  file: "#A Direct PATH to a .desktop file from ${SBUILD_OUTDIR} | ${SBUILD_TMPDIR}"
  dir: "#A Direct PATH to a Directory that contains at least 1 .Desktop"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] This is applicable only if <mark style="color:purple;">**`$pkg_type`**</mark> is a portable format like [**AppImage**](/formats/packages/appimage), [**FlatImage**](/formats/packages/flatimage) etc
* [x] This will be downloaded/copied & saved as <mark style="color:purple;">**`${SBUILD_PKG}.desktop`**</mark> inside as <mark style="color:orange;">**`${SBUILD_OUTDIR}/${SBUILD_PKG}.desktop`**</mark>
* [x] If used, it can only contain (One of these or all):

> - [x] <mark style="color:purple;">**`url`**</mark> : Is always preferred as the <mark style="color:orange;">**1st Choice**</mark>, even if used with others
> - [x] <mark style="color:purple;">**`file`**</mark> : Is ONLY preferred, if <mark style="color:purple;">**`url`**</mark> was **non-existent/empty**, as the <mark style="color:orange;">**2nd Choice**</mark>
> - [x] <mark style="color:purple;">**`dir`**</mark> : Is ONLY preferred, if both <mark style="color:purple;">**`url`**</mark> & <mark style="color:purple;">**`file`**</mark> are **non-existent/empty**, as the <mark style="color:orange;">**3rd & Final Choice**</mark>

{% code overflow="wrap" %}

```yaml
#Another Example
desktop:
 #Can contain one of (or all of): url, file, dir
  url: "https://example.com/example.desktop"
  #If you only use `/example.desktop` or `example.desktop`, it is assumed as: ${SBUILD_OUTDIR}/example.desktop
  #Here, we specify explictly to use ${SBUILD_TMPDIR}
  file: "${SBUILD_TMPDIR}/example.desktop" 
  #You can just use `/usr/share` or `usr/share`, it is assumed as: ${SBUILD_OUTDIR}/usr/share
  dir: "usr/share" #will search in ${SBUILD_OUTDIR}/usr/share
```

{% endcode %}

{% hint style="info" %} <mark style="color:purple;">**`file`**</mark> supports wildcard glob (<mark style="color:orange;">**`*`**</mark>) pattern

{% code overflow="wrap" %}

```yaml
desktop:
#Will search for a *.desktop file in ${SBUILD_TMPDIR} (picks first match)
  file: "${SBUILD_TMPDIR}/*.desktop"
```

{% endcode %}
{% endhint %}

{% hint style="info" %} <mark style="color:purple;">**`dir`**</mark> supports wildcard glob (<mark style="color:orange;">**`*`**</mark>) pattern

<pre class="language-yaml"><code class="lang-yaml">desktop:
  dir: "${SBUILD_OUTDIR}/usr/share/applications/assets*" 
#Will search inside all these dir (picks first match):
<strong># ${SBUILD_OUTDIR}/usr/share/applications/assets-extras
</strong><strong># ${SBUILD_OUTDIR}/usr/share/applications/assets_res
</strong># ${SBUILD_OUTDIR}/usr/share/applications/assetsXYZ
</code></pre>

{% endhint %}

{% hint style="info" %}
**This MAY BE OVERWRITTEN**, if <mark style="color:purple;">**`x_exec.run`**</mark> *does something to the file*, otherwise is used as **the default&#x20;**<mark style="color:purple;">**`.Desktop`**</mark> file
{% endhint %}


# 10.GhcrPkg

Fixed GHCR path (TYPE: NON\_ENFORCED)

```yaml
ghcr_pkg: "my-package"
```

* [x] Sets a fixed GHCR (GitHub Container Registry) path for the package (**TYPE:** <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] If not specified, the GHCR path is dynamically generated from `pkg_id`
* [x] Useful when you want a specific container name different from the auto-generated one

{% hint style="info" %}
This field is optional. Most packages don't need it as the auto-generated path works well.
{% endhint %}


# 11.HomePage

URLs to homepage, project page ,source code (Git/SVN/etc) (TYPE: NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
homepage:
  - "https://mypkg.net"
  - "https://mypkg.readthedocs.io"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] This contains the URLs to homepage, project page & source code (Git/SVN/etc)
* [x] This should **NOT BE CONFUSED** with [<mark style="color:purple;">**`src_url`**</mark>](/sbuild/specification/18.sourceurl) which contains URLs to the page that contains the <mark style="color:orange;">**`download_link`**</mark>
* [x] Can have single or multiple entries
* [x] Use [**repology/projects/$pkg/information**](https://repology.org/projects/) to quickly fetch this Information


# 12.Icon

Fetch Icon/Logo file from Remote/Local (SBUILD) Source (TYPE: NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
icon:
 #Can contain one of (or all of): url, file, dir
 #If it contains multiple (or all), the builder WILL STOP UPON FIRST successful Icon/Log file MATCH (Tries PNG, else SVG)
  url: "#A Direct RAW URL to download a icon/logo file"
  file: "#A Direct PATH to a icon/logo file from ${SBUILD_OUTDIR} | ${SBUILD_TMPDIR}"
  dir: "#A Direct PATH to a Directory that contains at least 1 icon/logo"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] Only One entry is supported
* [x] If <mark style="color:purple;">**`$pkg_type`**</mark> is a [binary format](/formats/binaries), then this is used only for <mark style="color:blue;">**`soar`**</mark><mark style="color:orange;">**`query/info`**</mark>
* [x] If <mark style="color:purple;">**`$pkg_type`**</mark> is a [package format](/formats/packages) like [AppImage](/formats/packages/appimage), [FlatImage](/formats/packages/flatimage), then it is downloaded & saved as <mark style="color:orange;">**`.DirIcon`**</mark> as <mark style="color:orange;">**`${SBUILD_OUTDIR}/.DirIcon`**</mark>
* [x] If used, it can only contain (One of these or all):

> - [x] <mark style="color:purple;">**`url`**</mark> : Is always preferred as the <mark style="color:orange;">**1st Choice**</mark>, even if used with others
> - [x] <mark style="color:purple;">**`file`**</mark> : Is ONLY preferred, if <mark style="color:purple;">**`url`**</mark> was **non-existent/empty**, as the <mark style="color:orange;">**2nd Choice**</mark>
> - [x] <mark style="color:purple;">**`dir`**</mark> : Is ONLY preferred, if both <mark style="color:purple;">**`url`**</mark> & <mark style="color:purple;">**`file`**</mark> are **non-existent/empty**, as the <mark style="color:orange;">**3rd & Final Choice**</mark>

{% code overflow="wrap" %}

```yaml
#Another Example
icon:
 #Can contain one of (or all of): url, file, dir
  url: "https://example.com/example.png"
  #If you only use `/example.png` or `example.png`, it is assumed as: ${SBUILD_OUTDIR}/example.png
  #Here, we specify explictly to use ${SBUILD_TMPDIR}
  file: "${SBUILD_TMPDIR}/example.png" 
  #You can just use `/usr/share` or `usr/share`, it is assumed as: ${SBUILD_OUTDIR}/usr/share
  dir: "usr/share" #will search in ${SBUILD_OUTDIR}/usr/share
```

{% endcode %}

{% hint style="info" %} <mark style="color:purple;">**`file`**</mark> supports wildcard glob (<mark style="color:orange;">**`*`**</mark>) pattern

{% code overflow="wrap" %}

```yaml
icon:
#Will search for a *.png file in ${SBUILD_TMPDIR} (picks first match)
  file: "${SBUILD_TMPDIR}/*.png"
```

{% endcode %}
{% endhint %}

{% hint style="info" %} <mark style="color:purple;">**`dir`**</mark> supports wildcard glob (<mark style="color:orange;">**`*`**</mark>) pattern

<pre class="language-yaml"><code class="lang-yaml">icon:
  dir: "${SBUILD_OUTDIR}/usr/share/applications/icons*" 
#Will search inside all these dir (picks first png, else first svg):
<strong># ${SBUILD_OUTDIR}/usr/share/applications/icons128
</strong><strong># ${SBUILD_OUTDIR}/usr/share/applications/icons256
</strong># ${SBUILD_OUTDIR}/usr/share/applications/iconsXYZ
</code></pre>

{% endhint %}

{% hint style="info" %}

* This <mark style="color:red;">**MAY BE OVERWRITTEN**</mark>, if <mark style="color:purple;">**`x_exec.run`**</mark> does something to the file (example: It produces it's own <mark style="color:orange;">**`${SBUILD_PKG}.{png|svg}`**</mark> file)**,** otherwise is used as the default <mark style="color:orange;">**`.DirIcon`**</mark> & <mark style="color:orange;">**`${SBUILD_OUTDIR}/${SBUILD_PKG}.png`**</mark> file
* The <mark style="color:purple;">**`icon`**</mark> file is renamed to <mark style="color:orange;">**`${SBUILD_OUTDIR}/${SBUILD_PKG}.{png|svg}`**</mark>based on the <mark style="color:blue;">**ImageType**</mark>
  {% endhint %}


# 13.License

SPDX License (TYPE: NON\_ENFORCED)

* [x] This is Optional & can be left empty or removed completely (**TYPE**: <mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] Is copied (installed) as [<mark style="color:orange;">**$APP\_PATH**</mark>](#user-content-fn-1)[^1]<mark style="color:orange;">**/**</mark><mark style="color:blue;">**LICENSE**</mark>
* [x] Use [**repology/projects/$pkg/information**](https://repology.org/projects/) to quickly fetch this Information
* [x] If used, it can only contain (One of these):

{% hint style="success" %}

* [x] <mark style="color:purple;">**`url`**</mark> : Is always preferred as the **1st Choice**, & **CAN NOT BE** used with others.
* [x] This refers to a raw url containing a <mark style="color:blue;">**`LICENSE`**</mark> file & is downloaded + saved at: <mark style="color:orange;">**`${SBUILD_OUTDIR}/LICENSE`**</mark>
* [x] If used, **only ONE entry is supported**

<pre class="language-yaml" data-overflow="wrap"><code class="lang-yaml">#Example ONLY
<strong>license:
</strong>  - id: "MIT"
    url: "https://raw.githubusercontent.com/pkgforge/soar/refs/heads/main/LICENSE" #Would be downloaded &#x26; saved as ${SBUILD_OUTDIR}/LICENSE
</code></pre>

{% endhint %}

{% hint style="success" %}

* [x] <mark style="color:purple;">**`file`**</mark> : Is ONLY preferred, if <mark style="color:purple;">**`url`**</mark> was NOT USED ( <mark style="color:orange;">**non-existent/empty**</mark>), as the **2nd Choice**
* [x] This refers to a direct path to a <mark style="color:blue;">**`LICENSE`**</mark> file produced during an sbuild.
* [x] While Multiple Entries are supported, the builder will stop checking upon the first successful find
* [x] The first valid <mark style="color:blue;">**`LICENSE`**</mark> file is copied to <mark style="color:orange;">**`${SBUILD_OUTDIR}/LICENSE`**</mark>

{% code overflow="wrap" %}

```yaml
#Example ONLY
# (All paths are assumed to be inside ${SBUILD_OUTDIR} i.e ${SBUILD_OUTDIR} == /
license:
  - id: "MIT"
    file: "/MIT.license" #Is assumed as ${SBUILD_OUTDIR}/MIT.license & copied to ${SBUILD_OUTDIR}/LICENSE
  - id: "GPL3"  
    file: "/SBUILD_TMPDIR/foo/bar.license" #Is assumed as ${SBUILD_OUTDIR}/SBUILD_TMPDIR/foo/bar.license & copied to ${SBUILD_OUTDIR}/LICENSE, IF & ONLY IF ${SBUILD_OUTDIR}/MIT.license wasn't found
```

{% endcode %}
{% endhint %}

{% hint style="warning" %}
If you can't find a direct URL to the <mark style="color:blue;">**`LICENSE`**</mark> file & it's also not produced during build anywhere inside <mark style="color:orange;">**`${SBUILD_OUTDIR}`**</mark> , then you may use:

* [x] [<mark style="color:purple;">**`spdx-identifier`**</mark>](https://spdx.org/licenses/): Any (or Multiple if applicable) of the identifiers listed at: <https://spdx.org/licenses/>, as the **3rd & Final Choice**

```yaml
#Example ONLY
license:
  - "GPL-2+"
  - "GPL-2.0"
  - "GPL-2.0-only"
  - "GPL-2.0-or-later"
  - "GPL2"
  - "GPLv3"
  - "Unfree"
```

{% endhint %}

[^1]: $APP\_PATH refers to the directory soar installs the respective APP


# 14.Maintainer

Author/Maintainer of the $pkg.SBUILD script  (TYPE: NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
maintainer:
  - "Azathothas (https://github.com/Azathothas)"
  - "QaidVoid (Qaid@Qaidvoid.dev)"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] This shows the author/maintainer of the <mark style="color:purple;">**`$pkg.SBUILD`**</mark> script
* [x] A single pkg can have multiple maintainers & contact details or websites can be embedded inside <mark style="color:orange;">`()`</mark>
* [x] Can have single or multiple entries

{% hint style="info" %}

* **This is NOT the author/developer/maintainer of the package**
* You will usually **add yourself** to this field
  {% endhint %}


# 15.Note

Note about the pkg (TYPE: NON\_ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
note:
  - "Some note"
  - "Some other note"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:blue;">**`NON_ENFORCED`**</mark>)
* [x] This contains extra information about the <mark style="color:purple;">**`$pkg`**</mark> such as setup information or errors & quirk.
* [x] Can have single or multiple entries


# 16.Provides

List of Binaries/Packages Generated during Build (TYPE: RECOMMENDED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
# $pkg itself will always be a default value, so not needed if contains only 1 program and that 1 program is $pkg itself
provides:
  - "prog-a"
  - "prog-b"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**: <mark style="color:green;">**`RECOMMENDED`**</mark>)
* [x] This lists all programs that are fetched/built during the <mark style="color:purple;">**`x_exec.run`**</mark> part.
* [x] If this field is empty or doesn't exist, the interpreter will use <mark style="color:purple;">**`$pkg`**</mark> as the only value of <mark style="color:purple;">**`provides`**</mark> by default.
* [x] If this field exists, soar will treat it as a <mark style="color:purple;">**`$pkg`**</mark> family containing all programs from <mark style="color:purple;">**`provides`**</mark>
* [x] <mark style="color:orange;">**`soar install`**</mark> <mark style="color:purple;">**`$pkg`**</mark> by default, will install all programs from <mark style="color:purple;">**`provides`**</mark>. This is the same as `$pkg` when `provides` is empty/nonexistent.
* [x] <mark style="color:orange;">**`soar install`**</mark> <mark style="color:purple;">**`$pkg/$prog`**</mark> will only install <mark style="color:purple;">**`$prog`**</mark> from the <mark style="color:purple;">**`$pkg`**</mark>'s <mark style="color:orange;">**`.SBUILD`**</mark>
* [x] Can have single or multiple entries

***

### alias

{% hint style="info" %}
It is possible to specify <mark style="color:blue;">**aliases**</mark> with <mark style="color:purple;">**`:`**</mark> as a separator, **provided that the original $prog is the first value** (Only used for <mark style="color:blue;">**METADATA**</mark>)

{% code overflow="wrap" %}

```yaml
#Example ONLY
# $pkg itself will always be a default value, so not needed if contains only 1 program and that 1 program is $pkg itself, however we can name it explictly if the prog is also known by another name with :
provides:
  - "prog-original:prog-alias"
  #Example:
  # - "chaos:chaos-cli" --> Chaos is same as `.pkg`, but since `chaos-cli` is also defined, searching for either chaos:chaos-cli will return the same result
  
#If a $pkg has multiple aliases, it can be specified by using : before each alias
provides:
  - "prog-original:prog-alias-1:prog-alias-2:prog-alias-3"
```

{% endcode %}
{% endhint %}

***

### symlink

{% hint style="info" %}
It is possible to specify <mark style="color:blue;">**symlinks**</mark> with <mark style="color:purple;">**`==`**</mark> as a separator, **provided that the original $prog is the first value** ([<mark style="color:orange;">**`INSTALL_ONLY`**</mark>](#user-content-fn-1)[^1])

{% code overflow="wrap" %}

```yaml
#Example ONLY
# $pkg itself will always be a default value, so not needed if contains only 1 program and that 1 program is $pkg itself, however we can name it explictly if the prog is also meant to be Symlinked with known by another name with ==
provides:
  - "prog-original==prog-symlink"
  #Example:
  # - "busybox==whoami" --> busybox is the main program , but since `whoami` is also defined, soar will create a whoami symlink that points to buysbox
  
#If a $pkg has multiple symlinks, it can be specified in this way
provides:
  - "prog-original==prog-symlink-1"
  - "prog-original==prog-symlink-2"
  - "prog-original==prog-symlink-3"
```

{% endcode %}
{% endhint %}

#### symlink-only

{% hint style="warning" %}
It is possible to specify a symlink-only[^2] operation with <mark style="color:purple;">**`=>`**</mark> as a separator, **provided that the original $prog is the first value** ([<mark style="color:orange;">**`INSTALL_ONLY`**</mark>](#user-content-fn-3)[^3])

**This also means, Only the&#x20;**<mark style="color:orange;">**SYMLINK**</mark>**&#x20;would be available in&#x20;**<mark style="color:orange;">**$PATH**</mark>

{% code overflow="wrap" %}

```yaml
provides:
  - "prog-original=>prog-new" # prog-original would get symlinked as prog-new
 #Example:
  # - "ripgrep=>rg" --> ripgrep is the main program , but since `rg` is also defined with =>, soar will symlink the ripgrep package as rg in BINDIR
  #Only renames the symlink, the original name will still be present in INSTALL_DIR
  #When Invoked from the cmdline, only rg would be found
```

{% endcode %}
{% endhint %}

***

[^1]: Not supported or understood by the builder\
    Rather, soar will parse & perform it

[^2]: The symlink, NOT the real package itself

[^3]: Not supported or understood by the builder,\
    Rather, soar will parse & perform it\
    Just use x\_exec.run to do it & specify correct provides from the get-go\\


# 17.Repology

Repology Project Name (TYPE: RECOMMENDED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
repology:
  - "mypkg"
  - "mypkg-bin"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:green;">**`RECOMMENDED`**</mark>)
* [x] This contains the package name that [**repology**](https://repology.org/projects/) uses.
* [x] Can have single or multiple entries


# 18.SourceURL

URL to the download/source page which contains the download link (TYPE: ENFORCED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
src_url:
  - "https://gitlab.com/mypkg"
  - "https://github.com/mypkg"
```

{% endcode %}

* [x] This **MUST contain at least `1` URL** (**TYPE**:<mark style="color:red;">**`ENFORCED`**</mark>)
* [x] This contains the URL to the <mark style="color:orange;">**`download/source`**</mark> page which contains the download link for the <mark style="color:purple;">**`pkg`**</mark>
* [x] This should **`NOT BE CONFUSED`** with [<mark style="color:purple;">**`homepage`**</mark>](/sbuild/specification/11.homepage)
* [x] Can have only single or multiple entries


# 19.Tag

Tags categorizing the pkg (TYPE: RECOMMENDED)

{% code overflow="wrap" %}

```yaml
#Example ONLY
tag:
  - "app-emulation"
  - "emulators"
  - "game"
  - "system"
```

{% endcode %}

* [x] This is Optional & can be left empty or removed completely (**TYPE**:<mark style="color:green;">**`RECOMMENDED`**</mark>)
* [x] This contains tags for better <mark style="color:orange;">**`soar search`**</mark> as the existing [<mark style="color:purple;">**`Category`**</mark>](/sbuild/specification/7.category) is quite Limited & Strict
* [x] Can have single or multiple entries

{% hint style="info" %}
Example on Github, the tag could be remote-desktop, rdp etc

<img src="/files/9huF7szPlg31C7r6pvf6" alt="" data-size="original">
{% endhint %}


# 20.x\_exec

Build/Download execution (TYPE: ENFORCED)

## Core Fields

```yaml
x_exec:
  shell: "bash"
  pkgver: |
    # Commands to fetch version (output only the version string)
    curl -qfsSL "https://api.github.com/repos/owner/repo/releases/latest" | jq -r '.tag_name'
  run: |
    # Commands to build/download the package
    # Output must be placed in ${SBUILD_OUTDIR}
```

* `shell`: Interpreter to use (bash, sh, fish, nu, zsh, etc.)
* `pkgver`: Fetches version, saved to `${SBUILD_OUTDIR}/${SBUILD_PKG}.version` and `${PKG_VER}` env
* `run`: Main build/download script, must produce [required output files](/sbuild/instructions/needed_files)

***

## Optional Fields

### arch

Restrict to specific architectures. Build terminates if host arch doesn't match.

```yaml
x_exec:
  arch:
    - "aarch64"
    - "x86_64"
```

### os

Restrict to specific operating systems.

```yaml
x_exec:
  os:
    - "linux"
    - "freebsd"
```

### host

Combined arch + os restriction.

```yaml
x_exec:
  host:
    - "aarch64-Linux"
    - "x86_64-Linux"
```

### conflicts

Packages to uninstall after successful build.

```yaml
x_exec:
  conflicts:
    - "old.pkg.id"
```

### depends

Packages to install before running `x_exec.run`.

```yaml
x_exec:
  depends:
    - "required.pkg.id"
```

### entrypoint

Path to main binary when it's not at `${SBUILD_OUTDIR}/${SBUILD_PKG}`.

```yaml
x_exec:
  entrypoint: "${SBUILD_OUTDIR}/bin/my-binary"
```


# Instructions

How to write an SBUILD

## Prerequisites

* [x] [Install Soar](https://soar.qaidvoid.dev/installation)
* [x] Read the [Spec](https://docs.pkgforge.dev/sbuild/specification)
* [x] View [examples](https://github.com/pkgforge/soarpkgs/tree/main/packages)

***

## Write

1. Copy the [template](https://github.com/pkgforge/soarpkgs/blob/main/templates/generic.SBUILD.yaml)
2. Fill in the fields following the [spec](/sbuild/specification) and [examples](/sbuild/instructions/examples)
3. Validate with [sbuild-linter](https://github.com/pkgforge/sbuilder):

```bash
soar add "sbuild-linter"
sbuild-linter "./example.SBUILD"

# To test pkgver fetching
sbuild-linter "./example.SBUILD" --pkgver
```

4. Submit a [Pull Request](https://github.com/pkgforge/soarpkgs/compare) or [Issue](https://github.com/pkgforge/soarpkgs/issues/new/choose) with the `.validated` version

***

## Build

{% hint style="warning" %}
Use a sandbox or container when running untested SBUILDs.
{% endhint %}

```bash
soar add "sbuild"
sbuild "./example.SBUILD" --log-level "verbose" --keep --outdir "./SBUILD-TEST"
```


# Examples

SBUILD Examples

## Minimal

{% code overflow="wrap" %}

```yaml
#!/SBUILD ver @v1.0.0
pkg: "86box"
pkgver: "v4.2.1"
description: "Emulator of x86-based machines"
src_url:
  - "https://github.com/86Box/86Box"
x_exec:
  shell: "bash"
  pkgver: |
    curl -qfsSL "https://api.github.com/repos/86Box/86Box/releases/latest" | jq -r '.tag_name'
  run: |
    case "$(uname -m)" in
      aarch64)
        soar dl "https://github.com/86Box/86Box" --match "appimage,arm64" --exclude "x64,x86,zsync" -o "./${PKG}" --yes
        ;;
      x86_64)
        soar dl "https://github.com/86Box/86Box" --match "appimage,x86_64" --exclude "aarch64,arm,zsync" -o "./${PKG}" --yes
        ;;
    esac
```

{% endcode %}

## Full Example

{% code overflow="wrap" %}

```yaml
#!/SBUILD ver @v1.0.0

pkg: "86box"
pkg_id: "github.com.86Box.86Box"
pkg_type: "AppImage"
pkgver: "v4.2.1" #fixed version; omit for dynamic versioning
#ghcr_pkg: "86box" #optional: set fixed ghcr path

app_id: "net._86box._86Box"
build_util:
  - "curl#bin"
  - "jq#bin"
category:
  - "Emulator"
description: "Emulator of x86-based machines"
homepage:
  - "https://86box.net"
license:
  - id: "GPL-2.0"
    url: "https://github.com/86Box/86Box/raw/main/COPYING"
maintainer:
  - "Azathothas (https://github.com/Azathothas)"
note:
  - "You need to download ROMS: https://86box.readthedocs.io/en/latest/usage/roms.html"
provides:
  - "86box"
repology:
  - "86box"
src_url:
  - "https://github.com/86Box/86Box"
tag:
  - "emulator"
x_exec:
  host:
    - "aarch64-Linux"
    - "x86_64-Linux"
  shell: "bash"
  pkgver: |
    curl -qfsSL "https://api.github.com/repos/86Box/86Box/releases/latest" | jq -r '.tag_name'
  run: |
    case "$(uname -m)" in
      aarch64)
        soar dl "https://github.com/86Box/86Box" --match "appimage,arm64" --exclude "x64,x86,zsync" -o "./${PKG}" --yes
        ;;
      x86_64)
        soar dl "https://github.com/86Box/86Box" --match "appimage,x86_64" --exclude "aarch64,arm,zsync" -o "./${PKG}" --yes
        ;;
    esac
```

{% endcode %}

## Rolling Build

For packages without versioned releases (nightly, git HEAD):

{% code overflow="wrap" %}

```yaml
#!/SBUILD ver @v1.0.0

pkg: "example-nightly"
_rolling: true
description: "Nightly build example"
src_url:
  - "https://github.com/example/repo"
x_exec:
  shell: "bash"
  pkgver: |
    echo "nightly-$(date +%Y%m%d)"
  run: |
    # build from git HEAD
```

{% endcode %}


# Environment Variables

List of Environment Variables that are Accessible Inside x\_exec.run

{% hint style="danger" %} <mark style="color:orange;">**Anything else that's NOT Listed**</mark>**&#x20;here,&#x20;**<mark style="color:red;">**should NOT be Accessible**</mark>**&#x20;Inside&#x20;**<mark style="color:purple;">**x\_exec.run**</mark>**&#x20;context**
{% endhint %}

* [x] <mark style="color:orange;">**`${pkg}`**</mark>**&#x20;|&#x20;**<mark style="color:orange;">**`{PKG}`**</mark>

> - **Description**: The raw value of [<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg) from <mark style="color:purple;">**`.SBUILD`**</mark> <<mark style="color:green;">**ALWAYS**</mark> *Available*>
> - **ALWAYS USE** <mark style="color:orange;">**${PKG}**</mark> for **output**, example: <mark style="color:orange;">**${PKG}**</mark> (<mark style="color:blue;">**Main Binary**</mark>), <mark style="color:orange;">**${PKG}.png**</mark> (<mark style="color:blue;">**Icon**</mark>), <mark style="color:orange;">**${PKG}.desktop**</mark> (<mark style="color:blue;">**Desktop**</mark>) etc

* [x] <mark style="color:orange;">**`${pkg_id}`**</mark> | <mark style="color:orange;">**`${PKG_ID}`**</mark>

> - **Description**: The raw value of [<mark style="color:purple;">**`.pkg_id`**</mark>](/sbuild/specification/2.pkg) from <mark style="color:purple;">**`.SBUILD`**</mark> <<mark style="color:red;">**Empty**</mark> *if not Available*>

* [x] <mark style="color:orange;">**`${pkg_type}`**</mark> | <mark style="color:orange;">**`${PKG_TYPE}`**</mark>

> - **Description**: The raw value of [<mark style="color:purple;">**`.pkg_type`**</mark>](/sbuild/specification/2.pkg) from <mark style="color:purple;">**`.SBUILD`**</mark> <<mark style="color:red;">**Empty**</mark> *if not Available*>

* [x] <mark style="color:orange;">**`${pkg_ver}`**</mark> | <mark style="color:orange;">**`${PKG_VER}`**</mark>

> - **Description**: The raw value of [<mark style="color:purple;">**`.pkgver`**</mark>](/sbuild/specification/3.version) **OR** the output produced by [<mark style="color:purple;">**`x_exec.pkgver`**</mark>](/sbuild/specification/20.x_exec)from<mark style="color:purple;">**`.SBUILD`**</mark> <<mark style="color:green;">**ALWAYS**</mark> *Available*>
> - This is the same as the raw content of <mark style="color:orange;">**${SBUILD\_PKG}.version**</mark> file

* [x] <mark style="color:orange;">**`${SBUILD_PKG}`**</mark>

> - **Description**: The raw value of [<mark style="color:purple;">**`.pkg`**</mark>](/sbuild/specification/2.pkg) + [<mark style="color:purple;">**.pkg\_type**</mark>](/sbuild/specification/2.pkg) from <mark style="color:purple;">**`.SBUILD`**</mark> <<mark style="color:green;">**ALWAYS**</mark> *Available*>

* [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}`**</mark>

> - **Description**: The **Root** (<mark style="color:orange;">**Temporary**</mark>) <mark style="color:blue;">**Working Directory**</mark> [<mark style="color:purple;">**`x_exec.run`**</mark>](/sbuild/specification/20.x_exec) is Run From <<mark style="color:green;">**ALWAYS**</mark> *Available*>
> - **All** [**NEEDED Files**](/sbuild/instructions/needed_files) **must exist in this&#x20;**<mark style="color:orange;">**Directory**</mark>

* [x] <mark style="color:orange;">**`${SBUILD_TMPDIR}`**</mark>

> - **Description**: The <mark style="color:purple;">**SBUILD\_TEMP**</mark> <mark style="color:blue;">**Directory**</mark> inside <mark style="color:orange;">**${SBUILD\_OUTDIR}**</mark> (**PATH**: <mark style="color:orange;">**`${SBUILD_OUTDIR}/`**</mark><mark style="color:purple;">**`SBUILD_TEMP`**</mark>), used for storing *NON-NEEDED* Files <<mark style="color:green;">**ALWAYS**</mark> *Available*>
> - Use this dir to do Additional Steps, **keep the main&#x20;**<mark style="color:orange;">**${SBUILD\_OUTDIR}**</mark>**&#x20;clutter free**

* [x] <mark style="color:orange;">**`${USER_AGENT}`**</mark>

> - **Description**: <mark style="color:blue;">**User-Agent**</mark> from **Host** <<mark style="color:red;">**Empty**</mark> *if not Available*>
> - If available & inherited, the <mark style="color:orange;">**Runner**</mark> will use it as the User Agent Header for all **HTTP** Requests.
> - If used <mark style="color:orange;">`--no-hostenv`</mark>, then this <mark style="color:purple;">**ENV\_VAR**</mark> is **NOT TO BE INHERITED/INSERTED AT ALL**

* [x] [<mark style="color:orange;">**`${GITHUB_TOKEN}`**</mark>](https://cli.github.com/) | [<mark style="color:orange;">**`${GH_TOKEN}`**</mark>](https://cli.github.com/)

> - **Description**: <mark style="color:blue;">**Github Token**</mark> from **Host** <<mark style="color:red;">**Empty**</mark> *if not Available*>
> - If available & inherited, the <mark style="color:orange;">**Runner**</mark> will use it as the Token to make **Github API** Requests.
> - If used <mark style="color:orange;">`--no-hostenv`</mark>, then this <mark style="color:purple;">**ENV\_VAR**</mark> is **NOT TO BE INHERITED/INSERTED AT ALL**

* [x] [<mark style="color:orange;">**`${GITLAB_TOKEN}`**</mark>](https://gitlab.com/gitlab-org/cli) | [<mark style="color:orange;">**`${GL_TOKEN}`**</mark>](https://gitlab.com/gitlab-org/cli)

> - **Description**: <mark style="color:blue;">**Gitlab Token**</mark> from **Host** <<mark style="color:red;">**Empty**</mark> *if not Available*>
> - If available & inherited, the <mark style="color:orange;">**Runner**</mark> will use it as the Token to make **Gitlab API** Requests.
> - If used <mark style="color:orange;">`--no-hostenv`</mark>, then this <mark style="color:purple;">**ENV\_VAR**</mark> is **NOT TO BE INHERITED/INSERTED AT ALL**

* [x] [<mark style="color:orange;">**`${HF_TOKEN}`**</mark>](https://huggingface.co/docs/huggingface_hub/en/guides/cli)

> - **Description**: <mark style="color:blue;">**HuggingFaceHub Token**</mark> from **Host** <<mark style="color:red;">**Empty**</mark> *if not Available*>
> - If available & inherited, the <mark style="color:orange;">**Runner**</mark> will use it as the Token to make **HF API** Requests.
> - If used <mark style="color:orange;">`--no-hostenv`</mark>, then this <mark style="color:purple;">**ENV\_VAR**</mark> is **NOT TO BE INHERITED/INSERTED AT ALL**

***

* [x] <mark style="color:blue;">**MISC**</mark>

{% hint style="info" %}
If <mark style="color:orange;">**`--no-hostenv`**</mark>is used, the <mark style="color:purple;">**`ENV VARS`**</mark> below are to be created from scratch based on the fallback that's described for each.
{% endhint %}

> * [x] <mark style="color:green;">**LANG**</mark>: The Locale Setting, If this is empty/non-existent (or used <mark style="color:orange;">`--no-hostenv`</mark>) , Use <mark style="color:orange;">**`C.UTF-8`**</mark> (<mark style="color:green;">**`LANG`**</mark>**`=`**<mark style="color:orange;">**`C.UTF-8`**</mark>)
> * [x] <mark style="color:green;">**LC\_ALL**</mark>: The Locale Setting, If this is empty/non-existent (or used <mark style="color:orange;">`--no-hostenv`</mark>) , Use <mark style="color:orange;">**`C.UTF-8`**</mark> (<mark style="color:green;">**`LC_ALL`**</mark>**`=`**<mark style="color:orange;">**`C.UTF-8`**</mark>)
> * [x] <mark style="color:green;">**PATH**</mark>: The <mark style="color:orange;">**`${PATH}`**</mark> from <mark style="color:blue;">**HOST**</mark>, if this is empty/non-existent (or used <mark style="color:orange;">`--no-hostenv`</mark>), Use: <mark style="color:orange;">**`${SOAR_BINPATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`**</mark> (Example: <mark style="color:green;">**`PATH`**</mark>**`=`**<mark style="color:orange;">**`/home/example/.local/share/soar/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`**</mark>)
> * [x] <mark style="color:green;">**PWD**</mark>: The Present Working Directory, this should be set to the **full realpath of** <mark style="color:orange;">**`${SBUILD_OUTDIR}`**</mark>, as the [<mark style="color:purple;">**`x_exec.run`**</mark>](/sbuild/specification/20.x_exec) is run from this dir. <<mark style="color:green;">**ALWAYS**</mark> *Available*> (Example: <mark style="color:green;">**`PWD`**</mark>**`=`**<mark style="color:orange;">**`/home/example/.local/share/soar/cache/sbuild/github.com.example.example.stable`**</mark>)
> * [x] <mark style="color:green;">**SHELL**</mark>: The value of [<mark style="color:purple;">**`x_exec.shell`**</mark>](/sbuild/specification/20.x_exec) **after resolving with env** so it prints **full realpath** of [<mark style="color:purple;">**`x_exec.shell`**</mark>](/sbuild/specification/20.x_exec) <<mark style="color:green;">**ALWAYS**</mark> *Available*> (<mark style="color:green;">**`SHELL`**</mark>**`=`**<mark style="color:orange;">**`/bin/bash`**</mark>)
> * [x] <mark style="color:green;">**TERM**</mark>: The terminal emulator, this is needed as some CLI progs behave unexpectedly without it. If this is empty/non-existent (or used <mark style="color:orange;">`--no-hostenv`</mark>), Use: <mark style="color:orange;">**`XTERM`**</mark> (<mark style="color:green;">**`TERM`**</mark>**`=`**<mark style="color:orange;">**`xterm`**</mark>)
> * [x] <mark style="color:green;">**USER**</mark>: The current **$USER** (<mark style="color:orange;">`whoami`</mark>) If this is empty/non-existent, it is to be determined & inserted manually. If used <mark style="color:orange;">`--no-hostenv`</mark>, then this <mark style="color:purple;">**ENV\_VAR**</mark> is **NOT TO BE INHERITED/INSERTED AT ALL**


# Output Files

Files produced at end of a successful SBUILD

* [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}`**</mark> <mark style="color:red;">**`ENFORCED`**</mark>

{% hint style="info" %}

* [x] **Description**: The actual <mark style="color:orange;">**binary/package**</mark> that was built
* [x] **Min\_Size**: <mark style="color:orange;">**`> 1KB`**</mark>
  {% endhint %}

- [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/.version`**</mark> | <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.version`**</mark> <mark style="color:red;">**`ENFORCED`**</mark>

{% hint style="info" %}
**Description**: <mark style="color:purple;">**`Version`**</mark> <mark style="color:orange;">**File**</mark>, Contains Version, *if empty, then Use Version based on* <mark style="color:orange;">**Date**</mark>/<mark style="color:orange;">**BSUM**</mark>
{% endhint %}

* [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/.desktop`**</mark> | <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.desktop`**</mark> <mark style="color:green;">**`OPTIONAL`**</mark>

{% hint style="info" %}

* [x] **Description**: <mark style="color:purple;">**`Desktop`**</mark> <mark style="color:orange;">**File**</mark>, Is *Edited/Fixed during Integration*
* [x] **Min\_Size**: <mark style="color:orange;">**`> 3BYTES`**</mark>
* [x] Only Available for [**Packages**](/formats/packages) **NOT** for [**Binaries**](/formats/binaries)
  {% endhint %}

- [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/.DirIcon`**</mark> | <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.DirIcon`**</mark> <mark style="color:green;">**`OPTIONAL`**</mark>

{% hint style="info" %}

* [x] **Description**: <mark style="color:orange;">**`DirIcon`**</mark>, *Preferred as* <mark style="color:purple;">**`Icon`**</mark> **if** <mark style="color:orange;">**${SBUILD\_OUTDIR}/${PKG}.png**</mark> OR <mark style="color:orange;">**${SBUILD\_OUTDIR}/${PKG}.svg**</mark> **DO NOT Exist**
* [x] **Min\_Size**: <mark style="color:orange;">**`> 20Bytes`**</mark>
* [x] Only Available for [**Packages**](/formats/packages) **NOT** for [**Binaries**](/formats/binaries)
  {% endhint %}

- [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.png`**</mark> | <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.svg`**</mark> <mark style="color:green;">**`OPTIONAL`**</mark>

{% hint style="info" %}

* [x] **Description**: *Preferred even* **if&#x20;**<mark style="color:orange;">**${SBUILD\_OUTDIR}/${PKG}.png**</mark> OR <mark style="color:orange;">**${SBUILD\_OUTDIR}/${PKG}.svg**</mark> **Exists due to Higher Resolution**
* [x] **Min\_Size**: <mark style="color:orange;">**`> 20BYTES`**</mark>
* [x] Only Available for [**Packages**](/formats/packages) **NOT** for [**Binaries**](/formats/binaries)
  {% endhint %}

- [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.appdata.xml`**</mark> | <mark style="color:orange;">**`${SBUILD_OUTDIR}/${PKG}.metainfo.xml`**</mark> <mark style="color:green;">**`OPTIONAL`**</mark>

{% hint style="info" %}

* [x] **Description**: *Prefer* <mark style="color:orange;">**metainfo.xml**</mark> over <mark style="color:orange;">**appdata.xml**</mark> as *<mark style="color:orange;">appdata.xml</mark> is now Legacy*
* [x] **Min\_Size**: <mark style="color:orange;">**`> 3BYTES`**</mark>
* [x] Only Available for [**Packages**](/formats/packages) **NOT** for [**Binaries**](/formats/binaries)
  {% endhint %}

- [x] <mark style="color:orange;">**`${SBUILD_OUTDIR}/LICENSE`**</mark> <mark style="color:green;">**`OPTIONAL`**</mark>

{% hint style="info" %}

* [x] **Description**: [<mark style="color:purple;">**`LICENSE`**</mark>](/sbuild/specification/13.license) <mark style="color:orange;">**File**</mark>, Contains License
* [x] **Min\_Size**: <mark style="color:orange;">**`> 3BYTES`**</mark>
* [x] Is **NOT Always Available**, a <mark style="color:orange;">**`WARN`**</mark>is sufficient when it doesn't exist
  {% endhint %}


# soarpkgs

Soar Package Repository

[Soarpkgs](https://github.com/pkgforge/soarpkgs) is the official package repository for Soar. It contains [SBUILD](/sbuild/introduction) recipes that define how packages are built.

## Structure

* **SBUILD recipes**: Build scripts in YAML format
* **bincache**: Prebuilt static binaries
* **pkgcache**: Prebuilt GUI applications (AppImages, etc.)

## Links

* [Repository](https://github.com/pkgforge/soarpkgs)
* [Package Search](https://pkgs.pkgforge.dev/)
* [Contribution Guide](/repositories/soarpkgs/contribution)
* [SBUILD Specification](/sbuild/specification)


# Metadata

Metadata Spec

Soarpkgs generates metadata for prebuilt packages:

* **bincache**: Static binaries
* **pkgcache**: GUI applications

## URLs

{% hint style="info" %}

* Add `.zstd` for compressed versions
* Formats: `.json`, `.sdb` (sqlite), `.sdb.zstd`
* `${HOST}` = `aarch64-Linux`, `x86_64-Linux`
  {% endhint %}

```
https://github.com/pkgforge/soarpkgs/releases/latest/download/bincache-${HOST}.json
https://github.com/pkgforge/soarpkgs/releases/latest/download/pkgcache-${HOST}.json
```

## Fields

{% code overflow="wrap" %}

```json5
// @string --> Single String Value
// @array --> Multiple (array) String Values

// Package identification
disabled: "false",         // If true, package is broken
host: "@string",           // Build target (arch-os)
pkg: "@string",            // Package name
pkg_family: "@string",     // Package family
pkg_id: "@string",         // Package ID
pkg_name: "@string",       // Install name (fallback to pkg)
pkg_type: "@string",       // Package type
pkg_webpage: "@string",    // Web index page

// App metadata
app_id: "@string",         // Application ID
appstream: "@string",      // Appstream XML URL
category: "@array",        // FreeDesktop categories
description: "@string",    // Package description
desktop: "@string",        // Desktop file URL
homepage: "@array",        // Project homepage
icon: "@string",           // Icon file
license: "@array",         // License info
maintainer: "@array",      // SBUILD maintainer
note: "@array",            // Additional notes
provides: "@array",        // Provided binaries
repology: "@array",        // Repology mapping
screenshots: "@array",     // Screenshots
src_url: "@array",         // Source URLs
tag: "@array",             // Tags

// Version info
version: "@string",        // Package version (HEAD- = built from source)
version_upstream: "@string", // Upstream version

// Build info
bsum: "@string",           // Blake3sum
build_date: "@string",     // Build date (YYYY-MM-DDTHH:MM:SS)
build_gha: "@string",      // GitHub Actions run URL
build_id: "@string",       // Build ID
build_log: "@string",      // Build log URL
build_script: "@string",   // SBUILD script URL

// GHCR info
download_url: "@string",   // Direct download URL
ghcr_blob: "@array",       // GHCR blob digest
ghcr_files: "@array",      // Artifacts in package
ghcr_pkg: "@string",       // GHCR package name + tag
ghcr_size: "@string",      // Total size (human readable)
ghcr_size_raw: "@string",  // Total size (bytes)
ghcr_url: "@string",       // Registry URL
shasum: "@string",         // SHA256sum
size: "@string",           // Package size (human readable)
size_raw: "@string",       // Package size (bytes)
snapshots: "@array"        // Version tags
```

{% endcode %}

## JQ Examples

```bash
# List all packages
curl -qfsSL "https://github.com/pkgforge/soarpkgs/releases/latest/download/bincache-$(uname -m)-$(uname -s).json" | jq -r '.[] | .pkg'

# Search for a package
curl -qfsSL "https://github.com/pkgforge/soarpkgs/releases/latest/download/bincache-$(uname -m)-$(uname -s).json" | jq -r '.[] | select(.pkg | test("qbittorrent"; "i"))'
```

## Security

Metadata is generated in [pkgforge/soarpkgs](https://github.com/pkgforge/soarpkgs). Verify provenance via [GitHub Attestations](https://github.com/pkgforge/soarpkgs/attestations).


# Contribution

Contribution Guidelines

1. Read the [SBUILD spec](/sbuild/specification) and [examples](https://github.com/pkgforge/soarpkgs/tree/main/packages)
2. Create an [Issue](https://github.com/pkgforge/soarpkgs/issues/new/choose) or [Pull Request](https://github.com/pkgforge/soarpkgs/compare)

We'll help fix any mistakes and provide feedback.


# Package Request

Request a Package

## Request a New Package

1. Check if the package already exists: [pkgs.pkgforge.dev](https://pkgs.pkgforge.dev/)
2. Open an issue: [github.com/pkgforge/soarpkgs/issues/new](https://github.com/pkgforge/soarpkgs/issues/new/choose)

Include:

* Package name and homepage
* Why you want it added
* Link to source/releases

## Add a Package Yourself

See the [contribution guide](/repositories/soarpkgs/contribution) and [SBUILD specification](/sbuild/specification).

## Criteria

Packages should:

* Have an active upstream
* Be open source (preferably)
* Not duplicate existing packages
* Have clear licensing


# Security

Security

* All packages are reviewed before inclusion
* Unofficial packages are [forked](https://github.com/orgs/pkgforge-community/repositories?q=fork%3Atrue+archived%3Afalse) to preserve history
* SBUILD requires [source](/sbuild/specification/18.sourceurl) links for transparency
* Unofficial packages include a [note](/sbuild/specification/15.note) indicating community origin


# FAQ

Frequently Asked Questions

### Is this an AUR?

Soarpkgs is inspired by the AUR concept but with a curated approach. Packages are reviewed by maintainers before inclusion.

***

### Cache

Cache refers to prebuilts from pkgforge's CI that Soar uses by default.

* [Bincache](/repositories/bincache): Prebuilt static binaries
* [Pkgcache](/repositories/pkgcache): Prebuilt GUI apps

***

### GLIBC vs MUSL

MUSL binaries use [mimalloc](https://github.com/microsoft/mimalloc) for performance parity with GLIBC. We also apply LTO and PIE optimizations.

***

### Portability

* Prebuilt packages are provided via cache to avoid build dependencies
* Heavy builds requiring containers are marked with a note
* Portable packages are tagged with `[PORTABLE]` in notes

***

### Custom Repositories

Soar supports adding [custom repositories](/repositories/external). You can use third-party repos or create your own.

***

### History

* **July 2023**: Toolpacks created
* **Sep 2024**: PkgCache created
* **Nov 2024**: Soarpkgs created


# bincache

Prebuilt Static Binaries

Bincache provides prebuilt static binaries from [soarpkgs](/repositories/soarpkgs).

## Usage

Packages from bincache are installed automatically when using Soar:

```bash
soar install package_name
```

## Links

* [Package Search](https://pkgs.pkgforge.dev/)
* [Metadata](/repositories/soarpkgs/metadata)
* [Contribution Guide](/repositories/soarpkgs/contribution)


# FAQ

Frequently Asked Questions

### Supported Platforms

Currently supported:

* `x86_64-Linux`
* `aarch64-Linux`

We'd like to support more architectures (riscv64, BSDs) but resources are limited.

***

### History & Lore

[**@Azathothas**](https://docs.pkgforge.dev/orgs/pkgforge-core/people#azathothas) used to be a bug bounty hunter. Setting up pentesting environments on remote servers was frustratingly slow - tools like [reconftw](https://github.com/six2dez/reconftw) would install entire toolchains just to get a few binaries.

Around **July 2023**, he started maintaining scripts to fetch precompiled binaries. What began as wrappers around [eget](https://github.com/zyedidia/eget) grew into multiple repos, eventually consolidating into [Toolpacks](https://github.com/Azathothas/Toolpacks). Toolpacks was archived on `2025-01-01` as part of a [major rewrite](https://github.com/pkgforge/bincache/issues/1).

Special mentions:

* [**@pwnwriter**](https://github.com/pwnwriter) created [Hysp](https://github.com/pwnwriter/hysp), the first package manager for Toolpacks (`Nov 2023`)
* [**@Xplshn**](https://github.com/xplshn) created [bdl](https://github.com/xplshn/Handyscripts/blob/master/bdl) → [BigDL](https://github.com/xplshn/bigdl) → [Dbin](https://github.com/xplshn/dbin)

Encouraged by community interest on [Lobsters](https://lobste.rs/s/iqxjee/poor_man_s_package_manager_only), [**@Azathothas**](https://docs.pkgforge.dev/orgs/pkgforge-core/people#azathothas) approached [**@QaidVoid**](https://github.com/QaidVoid), and [Soar](https://github.com/pkgforge/soar) received its first commit on **Oct 3, 2024**. The [PkgForge](https://github.com/pkgforge) organization was created on **Nov 4, 2024**.

#### Inspiration

This project builds on the work of: [andrew-d/static-binaries](https://github.com/andrew-d/static-binaries), [minos-org/minos-static](https://github.com/minos-org/minos-static), [mosajjal/binary-tools](https://github.com/mosajjal/binary-tools), [ryanwoodsmall/static-binaries](https://github.com/ryanwoodsmall/static-binaries), and others.

#### Further Reading

* [Static Linking Considered Harmful Considered Harmful](https://gavinhoward.com/2021/10/static-linking-considered-harmful-considered-harmful/)
* [Oasis Linux](https://github.com/oasislinux/oasis)
* [Stalix](https://stal-ix.github.io/STALIX.html)


# pkgcache

Prebuilt Portable Packages

Pkgcache provides prebuilt portable packages (AppImages, FlatImages, etc.) from [soarpkgs](/repositories/soarpkgs).

## Usage

Packages from pkgcache are installed automatically when using Soar:

```bash
soar install package_name
```

## Links

* [Package Search](https://pkgs.pkgforge.dev/)
* [Metadata](/repositories/soarpkgs/metadata)
* [Contribution Guide](/repositories/soarpkgs/contribution)


# FAQ

Frequently Asked Questions

### History & Lore

After [Toolpacks#28](https://github.com/Azathothas/Toolpacks/issues/28), [**@Azathothas**](https://docs.pkgforge.dev/orgs/pkgforge-core/people#azathothas) discovered portable package formats like [AppBundles](https://github.com/xplshn/pelf/), [AppImages](https://appimage.org/), [FlatImages](https://github.com/ruanformigoni/flatimage), and [RunImages](https://github.com/VHSgunzo).

These didn't fit Toolpacks' scope, so pkgcache was created **Sep 25, 2024**. It later became an ingestor for [soarpkgs](https://github.com/pkgforge/soarpkgs) after its creation on **Nov 4, 2024**.


# External (Custom Repos)

Custom Repositories

Soar supports adding custom repositories. You can either use an existing third-party repo or build your own.

## Adding a Custom Repo

Edit `~/.config/soar/config.toml`:

```toml
[[repositories]]
name = "my-repo"
url = "https://example.com/metadata.json"
```

Then sync:

```bash
soar sync
soar list 'my-repo'
```

## Building Your Own Repo

To create a compatible repository, generate metadata in the same format as [soarpkgs metadata](/repositories/soarpkgs/metadata). Host the JSON file anywhere accessible via URL.


# Nests

Self Hosted Mini Repositories for Soar

{% hint style="info" %}

* [x] <mark style="color:purple;">**Nests**</mark> are <mark style="color:orange;">**self hosted**</mark> repositories that build & release packages on their own Account/Org/Repository/Registry. Think of them as [homebrew's tap](https://docs.brew.sh/Taps), but easier & better.
* [x] For <mark style="color:blue;">**Developers**</mark>, Nests are an easy way to distribute their applications easily & seamlessly to the target system or any \*Unix based distro
* [x] For <mark style="color:blue;">**Users**</mark>, Nests are an easy (& quicker) way to get their favourite applications as soon as new releases are made without waiting for any package manager (including us) to package it first.
  {% endhint %}

***

## Developers

### Workflow

{% hint style="info" %}

* This will publish (mirror) your release on [**ghcr**](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages) & add a new **release** tag <mark style="color:green;">**`soar-nest`**</mark> to your repository
* The <mark style="color:green;">**`soar-nest`**</mark> release tag contains **JSON** metadata which soar uses to start ingesting your repository as a Nest.
  {% endhint %}

1. Write and add an [<mark style="color:purple;">**`.SBUILD`**</mark>](https://github.com/pkgforge/docs/blob/main/repositories/broken-reference/README.md) to your Project. You can [**ask us**](https://discord.gg/djJUs48Zbu) for help.
2. Add something like this to your release pipeline or as another workflow

{% code overflow="wrap" %}

```yaml
name: 🧰🛠️ Build Soar Package 📦📀

##Optional:
# Setup minisign & add the private key as secret: MINISIGN_KEY [${{ secrets.MINISIGN_KEY }}]
# Setup a Read-Only Underprivileged Github Token as secret: RO_GHTOKEN [${{ secrets.RO_GHTOKEN }}]
# Setup a Read-Only Underprivileged GitLab Token as secret: RO_GLTOKEN [${{ secrets.RO_GLTOKEN }}]

#These permissions are needed by main CI
permissions:
  attestations: write #Needed for Build Provenance & Attestations
  contents: write #Needed to create Release
  id-token: write #Needed for Build Provenance & Attestations
  packages: write #Needed to push to ghcr

#Assuming you just published a new release & the SBUILD doesn't build from source                 
on:
  #push:
  workflow_dispatch:
  release:
    types: [published]

jobs:

#Assuming you are targeting a stable release
  stable-release:
    uses: pkgforge/soarpkgs/.github/workflows/matrix_builds.yaml@main
    with:
      host: "ALL" #Otherwise aarch64-Linux OR x86_64-Linux
      sbuild-url: "https://github.com/${{ github.repository }}/raw/main/.github/SBUILD/latest.yaml" #Must always be a raw URL
      ghcr-url: "ghcr.io/${{ github.repository }}/stable" #Package will be pushed under this path
      pkg-family: "YOUR-PKG-PRIMARY-NAME" #Needed so soar can cross reference with other repos/nests
      debug: false #If set to true, will run everything with set -x
      logs: true #Will Attach the entire Logs + File as Workflow Artifact
      rebuild: true #Will rebuild even if ghcr tag already exists
```

{% endcode %}

3. Check for the <mark style="color:green;">**`soar-nest`**</mark> release tag (It is marked as a <mark style="color:blue;">**Pre-Release**</mark>)
4. Update your <mark style="color:blue;">**README**</mark> to include a one-liner

```bash
soar nest add nestname github:owner/repo
```

* When performing operations, the **nest name** must be **prepended with `nest-`**. For example:

  ```bash
  soar ls nest-nestname
  ```
* Instead of adding a GitHub repo, users may also directly provide a link to a **compatible SQLite database** or a **JSON metadata file**. Example:

  ```bash
  soar nest add mynest https://example.com/metadata.json.zstd
  soar nest add mynest https://example.com/packages.db
  ```

{% hint style="warning" %}

* All values must be **lowercase** : <https://github.com/oras-project/oras/discussions/930> , the workflow will forcefully change all values to match this.
  {% endhint %}

***

### Branding

{% hint style="warning" %}

* There's hardcoded stuff related to pkgforge, like filepath & some links.
* The filename/paths should be harmless and are present only in CI, not the final artifact
* However the api-urls, can't be removed as it is needed & used by soar-core. Fallbacks are automatically used in case our api-urls ever die, so this is also harmless.
* Finally, there's some branding in the logfile, To disable banners in logfiles, set <mark style="color:blue;">**`banner:`**</mark><mark style="color:red;">**`false`**</mark>
  {% endhint %}

***

### Security

{% hint style="danger" %}
By default, if you use our official workflows, you are pulling in code from our repos & then executing them on your repo with some over privileged perms. This is fine if you trust us not to do anything bad.

However, if you want to be extra careful, these mitagtions will help reduce any potential impact in case of incidents:

1. Always use the workflow on github actions with [github''s own JIT](https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication), so they would be generated & expired automatically.
2. Additionally, rather than using **pkgforge/soarpkgs/.github/workflows/matrix\_builds.yaml**<mark style="color:blue;">**@main**</mark> , audit our code, and then hardcode it to a particular commit hash **pkgforge/soarpkgs/.github/workflows/matrix\_builds.yaml@**<mark style="color:purple;">**${SHA}**</mark>
3. Additionally, separate your project's official project repo and soar's nest repo into two different repositories, so the token would have access to only soar's nest repo, not to your whole project
4. Additionally, read our code, and then rewrite it by yourself, on your own repo & run it on your own infra
   {% endhint %}

***

### Quirks

{% hint style="warning" %}

* Nests won't **work on forked repos** because github needs it to be a real (detached) repository in order to push packages associated with that repo to ghcr.
* **Setup time** for a build job can be as **high as 10 minutes**, this is because the runner needs to be able to handle any & all scenarios. This is intentional, as developers can use any build tool or even docker/podman without having to specify install deps in the SBUILD itself. However, if the sbuild **only needs curl/wget**, the runner **will still go through the whole setup phase**. Currently there's no solution for this problem, we thank you for your understanding & welcome any ideas over at: [**soarpkgs/discussions**](https://github.com/pkgforge/soarpkgs/discussions)
  {% endhint %}

***

## Users


# Chat

IRC/Chat Groups

* [**Discord**](https://discord.gg/djJUs48Zbu) : [**https://discord.gg/djJUs48Zbu**](https://discord.gg/djJUs48Zbu) (<mark style="color:green;">**`Active`**</mark>**&#x20;&&#x20;**<mark style="color:green;">**`Instant Response`**</mark>) \[<mark style="color:purple;">**`Primary`**</mark>]
* [~~**Telegram**~~](https://t.me/official_loonix/63949) ~~**:**~~ [~~https://t.me/official\_loonix/63949~~](https://t.me/official_loonix/63949) (<mark style="color:orange;">**`Late Response`**</mark>) \[<mark style="color:red;">**`Abandoned`**</mark>]
* [~~**Matrix**~~](https://matrix.to/#/#loonix:matrix.org) ~~:~~ [~~https://matrix.to/#/#loonix:matrix.org~~](https://matrix.to/#/#loonix:matrix.org) (<mark style="color:orange;">**`Late Response`**</mark>) \[<mark style="color:red;">**`Abandoned`**</mark>]

{% hint style="warning" %}
We have tried [Libera](https://libera.chat/), [Signal](https://signal.org/) & More. None offered us the better file sharing ability than [Telegram](https://telegram.org/faq), & none offered us as many features as [Discord](https://discord.com/). If you are concerned about Privacy, *the chat itself is public*, so is irrelevant for our needs. Thus, **please stop asking us to switch platforms**.
{% endhint %}

{% hint style="info" %}
If you had like to use other channels or email us, check this page for more info: <https://docs.pkgforge.dev/orgs/pkgforge-core/people>

**However, do note, it may go unanswered or get sent to Spam**
{% endhint %}


