A standalone, performance-focused Go command-line tool for orchestrating Flatpak application build pipelines, registry distribution (OCI), and static index site generation.
The CLI follows a Plumbing vs. Porcelain design:
- Plumbing (Primitives): Independent, highly-scoped, single-responsibility commands suited for complex workflows or customizable matrices.
- Porcelain (Convenience Wrappers): Standard high-level triggers that coordinate plumbing calls automatically in-memory.
For details on the Go package layout:
pkg/config: Configuration parsing and validations rules.pkg/record: Execution output records JSON contracts (record.json/labels.json).pkg/plan: Planning engine and git diff matrices logic.pkg/builder: system wrapper forflatpak-builder.pkg/importer: bundle downloader, checker, and rebind.pkg/oci: OSTree-to-OCI tags compiler and push transporters.pkg/signing: cryptographical in-memory detached GPG signatures.pkg/site: indexing merges and site aggregation engines.
The CLI parses settings from a configuration file, looking for aetherpak.yaml or aetherpak.yml in the local working directory by default.
Note
The configuration file can use both .yaml and .yml extensions. You can also specify a custom configuration file path at runtime using the --config flag or override any configuration parameter using environment variables prefixed with AETHERPAK_ (e.g. AETHERPAK_REGISTRY).
registry(string): The target OCI registry host (e.g.,ghcr.ioorquay.io).pages_url(string): The public URL where the repository landing page and index files are hosted.oci_repository(string): The target repository path/name for OCI distribution (replaces deprecatedremote_namefor OCI registry pushes).remote_name(string): The repository name configured in user Flatpak clients (defaults to<owner>-<repo>). Historically used for OCI registry pushes; now acts as a fallback foroci_repository(deprecated for registry pushes).output_dir(string): Base directory for all output assets (state, records, site, ccache, repo) unless overridden.no_sign(boolean): Set totrueto disable GPG signing of repositories and OCI images entirely (defaults tofalse).repo_title(string): Customized title shown on the landing page and.flatpakrepometadata (defaults to the value ofremote_name, which defaults to"aetherpak").repo_homepage(string): URL link for repository homepage metadata.runtime_repo(string): Fallback.flatpakrepoURL used to resolve dependencies (defaults to Flathub).channel_mappings(map[string]string): Key-value pairs mapping Git references (supporting glob wildcards likestaging/*) to target flatpak branches.
Customizes the look and feel of the generated landing page:
logo_url(string): URL to a custom repository header logo.favicon_url(string): URL to a page favicon file.accent_color(string): Hex color code defining the primary brand accent (defaults to#8b5cf6).footer_text(string): Custom text/HTML to display in the footer (defaults to"Powered by AetherPak").index_template(string): Local path to an alternative HTML file template to override index generation entirely. Supports structured Go HTML templates with access to repository applications and formatting helper functions (see Custom Index Templating below).
Global linter behavior configuration:
strict(boolean): Set totrueto fail builds if any linter warnings or errors are raised.ignore_rules(list[string]): Specificflatpak-builder-lintrule IDs to bypass.exceptions(list[string]): Inline list offlatpak-builder-lintrule IDs to bypass (alternative/alias forignore_rules). Can be overridden via theAETHERPAK_LINTER_EXCEPTIONSenvironment variable or the--linter-exceptionflag.exceptions_file(string): Local path to a JSON configuration file containing app-specific or wildcard linter exceptions (e.g."linter-exceptions.json"). Can be overridden via theAETHERPAK_LINTER_EXCEPTIONS_FILEenvironment variable or the--linter-exceptions-fileflag.
Fallback build configurations applied when individual application settings are omitted:
ccache(boolean): Enable compiler cache to speed up compilation.ccache_dir(string): Custom folder directory to store compiler cache assets.state_dir(string): Path to store intermediate state outputs (defaults to.state).run_linter(boolean): Set totrueto run linter checks on manifests and built repositories.builder_args(list[string]): Additional command-line flags to pass directly toflatpak-builder.no_install_deps(boolean): Disable automatic injection of--install-deps-fromflags when runningflatpak-builder(defaults tofalse).no_flathub(boolean): Disable automatic injection of theflathubremote as a dependency source (defaults tofalse).remotes(map[string]string | map[string]RemoteConfig): Map of Flatpak remote repository names to their configuration (pre-registered before build). Can be a simple URL string or an exploded map supporting:url(string, required): The flatpakrepo URL.gpg_verify(boolean, optional): Enable/disable GPG verification.gpg_key(string, optional): GPG public key (can be a local path, URL, or inline ASCII-armored GPG public key block).sig_verify_url(string, optional): Signature lookaside URL.
flatpaks(list[FlatpakDep]): Flatpak runtimes or SDK extensions/dependencies to pre-install before build. Each entry requires aremote(string) and aref(string).
A list of applications managed in the repository. Each entry supports the following settings:
id(string, required): The reverse-DNS Flatpak application identifier (e.g.org.example.App).branch(string): The release channel branch (defaults tostable).arches(list[string]): Target architectures to compile/import (defaults to[x86_64]).manifest(string): Local relative path to the Flatpak manifest file (required for source-based builds).runtime(string): Upstream runtime dependencies list (required for source-based builds).run-linter(boolean): Local toggle to execute linter validation checks.linter(block): Override block for linter strictness, ignore rules, and exceptions. Supportsstrict(boolean),ignore_rules(list[string]),exceptions(list[string]), andexceptions_file(string).ccache/ccache_dir/state_dir/builder_args/no_install_deps/no_flathub: Application-specific overrides for compilation parameters.remotes/flatpaks: Application-specific overrides/merges for Flatpak remotes and dependencies.bundles(map[string]Bundle): Prebuilt Flatpak bundle inputs mapped per architecture. Under each arch (e.g.x86_64):url(string, required): Download link to the.flatpakbundle.sha256(string, required): 64-character SHA-256 validation checksum of the file.
registry: ghcr.io
pages_url: https://flatpak.example.com
remote_name: example-repo
repo_title: "My Custom Flatpak Repository"
channel_mappings:
"main": "beta"
"staging/*": "alpha"
linter:
strict: true
ignore_rules: ["appstream-screenshot-missing"]
defaults:
ccache: true
run_linter: true
state_dir: ".builder-state"
builder_args: ["--sandbox", "--disable-rofiles-fuse"]
remotes:
flathub: https://dl.flathub.org/repo/flathub.flatpakrepo
custom_repo:
url: https://example.com/repo.flatpakrepo
gpg_verify: true
gpg_key: https://example.com/keys/gpg.key
sig_verify_url: https://example.com/signatures
flatpaks:
- remote: flathub
ref: org.gnome.Sdk//45
branding:
logo_url: "https://example.com/logo.png"
accent_color: "#a855f7"
footer_text: "Custom Repo Landing Page Footer"
apps:
- id: org.example.App
manifest: apps/org.example.App/manifest.json
runtime: gnome-50
arches: [x86_64, aarch64]
run-linter: true
remotes:
repoA: https://example.com/repoA.flatpakrepo
flatpaks:
- remote: repoA
ref: org.gnome.Sdk.ExtensionA//45
- id: com.example.Other
branch: beta
bundles:
x86_64:
url: https://upstream.com/Other_x86_64.flatpak
sha256: 2159fc643175dcf54f8b9293f48fb8b11577fa0ea5514ea47d4e3ef4431f13b1AetherPak automatically registers default exceptions for linter checks that are not applicable to self-hosted/independent repositories:
appstream-external-screenshot-urlappstream-screenshots-not-mirrored-in-ostree
Exceptions can be configured in two ways:
You can specify list of exceptions directly under the linter.exceptions property globally or per-app:
linter:
exceptions:
- appstream-screenshot-missing
- appstream-license-missingOr override them at runtime using:
- CLI repeatable flag:
--linter-exception <rule> - Env Var:
AETHERPAK_LINTER_EXCEPTIONS(comma-separated list of exceptions)
You can point to a linter exceptions JSON file containing app-specific or wildcard rules:
{
"org.example.App": [
"appstream-screenshot-missing",
"appstream-summary-too-long"
],
"*": [
"appstream-license-missing"
]
}This file path can be configured globally/per-app in aetherpak.yaml using the exceptions_file property, or overridden at runtime via:
- CLI flag:
--linter-exceptions-file <path> - Env Var:
AETHERPAK_LINTER_EXCEPTIONS_FILE(orAETHERPAK_LINTER_EXCEPTIONSif it has a.jsonsuffix)
When using a custom template file via the index_template config option, the --index-template flag, or the AETHERPAK_INDEX_TEMPLATE environment variable, AetherPak executes the template using Go's html/template engine.
The template is executed with a structured context containing all resolved repository, branding, signing, and application details.
The data structure passed to your custom template is defined as follows:
.RemoteName(string): The resolved Flatpak remote repository name..RepoTitle(string): The repository title..PagesURL(string): The URL where the repository static files are hosted..RepoHomepage(string): The homepage URL link..RuntimeRepo(string): The upstream runtime dependency repository URL..LogoURL(string): Custom repository header logo URL..LogoHTML(template.HTML): Pre-formatted HTML image element containingLogoURLif configured..FaviconURL(string): Custom page favicon file URL..AccentColor(string): Hex color code defining the brand accent color..FooterText(template.HTML): Custom footer HTML text..Signing(block):.Signing.Enabled(boolean): True if GPG signing is enabled..Signing.Fingerprint(string): GPG public key fingerprint..Signing.PublicKey(string): Path to the armored public key file (sigs/key.asc)..Signing.Lookaside(string): Path to the GPG signature lookaside directory (sigs).
.Apps(list): A list of preprocessed, structured application records:.ID(string): Reverse-DNS application identifier (e.g.org.example.App)..Name(string): Application name extracted from AppStream appdata, falling back to ID..Summary(string): Application summary description extracted from AppStream appdata..Icon(string): URL to the 64x64 application icon if defined..Branches(list): List of release channel branches sorted newest first:.Branch(string): Flatpak branch channel (e.g.stable,beta)..Arches(list[string]): Alphabetic list of supported architectures (e.g.[aarch64, x86_64])..Timestamp(int64): Latest build release Unix epoch timestamp..FormattedDate(string): Human-readable release date formatted asJan 02, 2006..InstalledSize(int64): Latest build installed size in bytes..DownloadSize(int64): Latest build download size in bytes..Commit(string): Flatpak commit identifier..RefFile(string): Path to target download flatpakref file (e.g.refs/org.example.App-stable.flatpakref)..InstallCmd(string): Helper command to install the application branch client-side.
You can use the following custom Go template helpers inside your custom template:
join <slice> <separator>: Joins a slice of strings using the specified separator.- Example:
{{join .Arches "/"}}->aarch64/x86_64
- Example:
formatSize <bytes>: Formats raw bytes into a human-readable string representation.- Example:
{{formatSize .InstalledSize}}->20 MB
- Example:
formatDate <timestamp> <layout>: Formats a UNIX epoch timestamp using a standard Go time layout.- Example:
{{formatDate .Timestamp "2006-01-02"}}->2026-06-01
- Example:
Here is a simple example of a custom HTML template:
<!DOCTYPE html>
<html>
<head>
<title>{{.RepoTitle}}</title>
<link rel="icon" href="{{.FaviconURL}}">
</head>
<body>
<h1>{{.RepoTitle}}</h1>
{{range .Apps}}
<div class="app-card">
{{if .Icon}}<img src="{{.Icon}}" width="64">{{end}}
<h2>{{.Name}} ({{.ID}})</h2>
<p>{{.Summary}}</p>
<h3>Releases</h3>
<ul>
{{range .Branches}}
<li>
Branch: <strong>{{.Branch}}</strong> | Arches: {{join .Arches ", "}}
<br>Released on: {{.FormattedDate}} | Size: {{formatSize .InstalledSize}}
<br>Install: <code>{{.InstallCmd}}</code>
</li>
{{end}}
</ul>
</div>
{{end}}
<footer>{{.FooterText}}</footer>
</body>
</html>--config <path>(optional path toaetherpak.yaml, defaults to check foraetherpak.yamllocally).--output-dir <path>(base directory for all output assets unless overridden).-v, --verbose(enable verbose debugging statements).--json-log(enable JSON formatted structured output logs).--plain(disable colors, emojis, and fancy formatting; plain text output).--no-color(alias for--plainto disable colors and fancy formatting).
Computes matrices for changed assets since a specific base SHA diff:
aetherpak plan --base-sha <sha> --workflow-path <path> --output jsonOptions:
--override-branch <branch>: Overrides the Flatpak branch (release channel) for all planned apps in the matrix.--force <app-id>: Rebuilds a specific app. Supports the Flatpak standardapp-id//branchref format (e.g.org.example.App//beta) to select that app and override its target branch.
Wraps flatpak-builder sandbox compilation:
aetherpak build --app-id org.example.App --manifest apps/manifest.json --arch x86_64 --linter-exception appstream-screenshot-missing --flatpak-remote flathub=https://dl.flathub.org/repo/flathub.flatpakrepo --flatpak-dep flathub:org.gnome.Sdk//45Options:
--app-id <app-id>: target application ID. Supports the Flatpak standardapp-id//branchref format (e.g.org.example.App//beta) to build that app and override its target branch.--flatpak-remote <name>=<url>: Repeatable flag to register Flatpak remotes before compiling.--flatpak-dep <remote>:<ref>: Repeatable flag to install Flatpak dependencies (runtimes, SDK extensions) before compiling.--no-install-deps: Disable automatic injection of--install-deps-fromflags when runningflatpak-builder.--no-flathub: Disable automatic injection of theflathubremote as a dependency source.
Ingests prebuilt bundles (.flatpak) and rebinds channels:
aetherpak import --app-id org.example.App --bundle-url https://... --bundle-sha256 <hex>Options:
--app-id <app-id>: target application ID. Supports the Flatpak standardapp-id//branchref format (e.g.org.example.App//beta) to override its target branch.
Converts repo branch to OCI image layer and pushes:
aetherpak push-oci --app-id org.example.App --registry ghcr.io --oci-repository my-org/my-appOptions:
--app-id <app-id>: target application ID. Supports the Flatpak standardapp-id//branchref format (e.g.org.example.App//beta) to filter repository refs or override its target branch.--gpg-key <path>: Local path to GPG private key used to sign image manifests.--no-sign: Disable GPG signing entirely (bypasses GPG signature step).--allow-unsigned: Allow pushing unsigned images if signing keys are missing.--dry-run: Simulate pushing OCI image without writing to remote registry or records.
Downloads old static index, merges recent cell records, and regenerates index listings:
aetherpak build-site --pages-url https://flatpak.my-org.com --site-dir _site --reconcile --index-template templates/custom_index.htmlOptions:
--gpg-key <path>: Local path to GPG private key used to export GPG public keys.--no-sign: Disable GPG signing and metadata export entirely.--allow-unsigned: Allow building unsigned index if GPG keys are missing.
Resolves the flatpak channel name from git ref metadata:
aetherpak resolve-channel --ref-type tag --ref-name v1.0.0Resolves the app-id, arch, and branch channel from an existing OSTree repository metadata:
aetherpak inspect-repo --repo-path repoGets, sets, or displays configuration parameter settings:
# Get a configuration value
aetherpak config get remote_name
aetherpak config get branding.logo_url
# Set a configuration value
aetherpak config set remote_name custom-remote
aetherpak config set branding.logo_url https://new-logo.png
# Show resolved configuration and active overrides
aetherpak config showCreates or modifies an aetherpak.yaml by adding one application from a local
manifest, a remote bundle URL (downloaded and fingerprinted), or a git
repository (added as a submodule, initialised recursively). Runs an interactive
wizard on a TTY; otherwise reads flags. A colored diff is shown before changes
are written unless --confirm/-y is given.
# Local manifest (app id detected from the manifest)
aetherpak add --manifest org.example.App.yaml
# Bundle URL (downloaded + fingerprinted; SHA-256 recorded)
aetherpak add --bundle-url https://example.com/app.flatpak --app-id org.example.App
# Git repository added as a submodule
aetherpak add --git https://example.com/repo.git
# Skip the diff confirmation
aetherpak add --manifest org.example.App.yaml -yOptions:
--manifest <path>/--bundle-url <url>/--git <url>: the source (exactly one in non-interactive mode).--git-manifest <path>: manifest path within the git repo (auto-detected if omitted).--submodule-path <path>: submodule destination (defaultmanifests/<reponame>).--app-id,--branch(Flatpak release channel, defaultstable),--arch(repeatable, defaults to the host architecture): overrides;app-idis derived from the manifest when omitted (only the bundle source requires--app-id).--bundle-sha256 <hex>: expected bundle checksum (verified; computed when omitted).- Build options (manifest/git sources only):
--install-deps-from-flathub(defaulttrue, appends--install-deps-from=flathub),--run-linter,--ccache, and--builder-arg <arg>(repeatable, free-form). -y,--confirm: skip the diff confirmation prompt.
The app id is read from the manifest — you are never prompted for it when it can be detected; a manifest that is found but lacks an id is reported as an error. The target config is resolved from --config/AETHERPAK_CONFIG, else an existing aetherpak.yaml/aetherpak.yml in the working directory, else a new aetherpak.yaml is created.
Chains compilation/importer and OCI push sequentially in-memory for target application(s):
# Config-driven publish
aetherpak publish --app-id org.example.App --registry ghcr.io
# One-off publish from local manifest
aetherpak publish --manifest apps/manifest.json --arch x86_64
# One-off publish from Flatpak bundle (URL or local path)
aetherpak publish --bundle https://example.com/app.flatpakOptions:
--app-id <id>: target application ID. Supports the Flatpak standardapp-id//branchref format (e.g.org.example.App//beta) to override its target branch.--manifest <path>: path to a local Flatpak manifest file (one-off publish, bypasses config).--bundle <url|path>: Flatpak bundle URL or path to import and publish (one-off publish, bypasses config).--confirm: skip interactive confirmation prompt when importing bundles.--arch <arch>: target CPU architecture (defaults to host architecture).--gpg-key <path>: Local path to GPG private key.--no-sign: Disable GPG signing entirely.--allow-unsigned: Allow publishing unsigned images if GPG keys are missing.--linter-exceptions-file <path>: Local path to linter exceptions file (JSON).--linter-exception <rule>: Repeatable flag to specify linter exceptions to ignore.--dry-run: Simulate publishing without writing to remote registry or records.
Coordinates the entire lifecycle: runs matrix planner, compiles/imports changed records concurrently, pushes artifacts, and builds site index layouts:
aetherpak release --base-sha <sha> --workers 4 --index-template templates/custom_index.htmlOptions:
--gpg-key <path>: Local path to GPG private key.--no-sign: Disable GPG signing entirely.--allow-unsigned: Allow releasing unsigned images/index if GPG keys are missing.--linter-exceptions-file <path>: Local path to linter exceptions file (JSON).--linter-exception <rule>: Repeatable flag to specify linter exceptions to ignore.--flatpak-remote <name>=<url>: Repeatable flag to register Flatpak remotes before compiling.--flatpak-dep <remote>:<ref>: Repeatable flag to install Flatpak dependencies before compiling.--dry-run: Simulate release process without writing to remote registry, records, or site directories.
Validates that required system dependencies are available, checks configuration files, and decrypts/verifies GPG keys:
aetherpak statusOptions:
--gpg-key <path>: Local path to GPG private key block(s) or file(s) to verify signing.--gpg-key-passphrase <passphrase>: GPG key passphrase to test decryption.--json: Outputs raw diagnostics status as JSON for script parsing.
Generates and serves a local landing page template preview using customizable dummy mock data or a live production index:
# Serve preview locally on port 8080 (default)
aetherpak preview
# Serve preview on port 9000 with a custom template
aetherpak preview --port 9000 --template templates/custom.html
# Generate static preview pages without serving (useful for CI/CD test site generation)
aetherpak preview --no-serve --apps=single --gpg=falseOptions:
--template, -t <path>: Local path to custom HTML repository index template (overrides configuration template).--default-template: Force using the default embedded landing page template, ignoring configuration/env settings.--live: Fetch live production index data instead of generating dummy data.--live-url <url>: Live Pages URL to download the index from (implicitly enables--live).--gpg: Enable GPG signing simulation for dummy data (defaults totrue).--apps <single|multiple>: Simulate single or multiple applications in dummy data (defaults tomultiple).--site-dir <path>: Destination directory for preview assets (defaults to_preview).--no-serve: Do not start a local HTTP server to preview the site (defaults tofalse).--port <port>: Port for local HTTP server (defaults to8080).
Clears builder compiler caches, state directories, template preview files, production site outputs, build-site records, and local OSTree repositories.
Requires confirmation unless --yes, -y, or --confirm is specified.
# Clean all temporary files (prompts for confirmation if interactive)
aetherpak clean
# Clean all temporary files without prompt (useful for CI)
aetherpak clean --yes
# Clean only compiler caches (ccache) and state directories
aetherpak clean --ccache --state --yesOptions:
--yes, -y: Skip confirmation prompt.--confirm: Skip confirmation prompt (deprecated alias for--yes).--ccache: Clean only builder compiler caches (.ccache).--state: Clean only builder state directories (.state).--preview: Clean only template preview directories (_preview).--site: Clean only production site build outputs (_site).--records: Clean only build-site input/output records (records).--repo: Clean only local OSTree repositories (repo).--ccache-dir <path>: Custom ccache directory path (defaults to.ccache).--state-dir <path>: Custom builder state directory path (defaults to.state).--preview-dir <path>: Custom preview site directory path (defaults to_preview).--site-dir <path>: Custom production site directory path (defaults to_site).--records-dir <path>: Custom records directory path (defaults torecords).--repo-path <path>: Custom OSTree repository path (defaults torepo).
Guidelines on compilation setup, local prerequisites, test harness drivers, and coding styles are documented in CONTRIBUTING.md.