Skip to content

The RetroDECK Alchemist - Guide

The alchemist.sh it is a Plugin‑Based Component Assembler.

Alchemy - noun - "A power or process that changes or transforms something in a mysterious or impressive way."

HEREBY BE WARNED!

The RetroDECK Alchemist is a magician / chef / bartender

Who, when given the proper instruction, can transmute one or more base source ingredients into the perfect creation of a component artifact.

Alchemy and cooking are, by definition, delicate.

  • The ingredients must be known and pure.
  • The recipe must be exact.
  • Any deviation from this process can be disastrous.

To achieve a perfect artifact, the ingredients must be well known.
Only by pulling ingredients when they are just right can we guarantee consistency.

To always chase the freshest ingredients all the time is a fool’s errand and would produce unreliable artifacts.

(Be careful with versioning of components for stable builds and lock them down.)


Repository Context

  • The alchemist.sh script is invoked from the …/components directory of the cloned repository:
    https://github.com/RetroDECK/components.git
  • The script’s location is flexible, but the calling directory matters:
  • If run inside a Git repo, $REPO_ROOT points to the repo’s root.
  • Otherwise, $REPO_ROOT defaults to the directory containing alchemist.sh.

Running Locally

Follow the steps below to build a component artifact locally using Alchemist.

1. Download Alchemist

Clone or download the Alchemist automation tools directory from the RetroDECK repository: Cooker: Alchemist

2. Prepare Your Component Directory

Place the component directory (containing the recipe and ingredient files) inside the alchemist directory using the following structure:

alchemist/<new-component-directory>/<files>

Your component directory must include a component_recipe.json and the other ingredient files.

3. Build the Artifact

From within the alchemist directory, run:

./alchemist.sh -f <component-directory>/component_recipe.json

4. Output

After a successful build, the generated artifact will be available at:

<component-directory>/artifact/<component-artifact>.tar.gz

5. Extract the Artifact

Extract the generated artifact: <component-artifact>.tar.gz

This will create a new component directory.

6. Install the Component

Move the extracted component directory into RetroDECK’s internal components directory.

Note:

The installation path depends on whether RetroDECK is installed locally (user) or system-wide.
A system-wide installation requires sudo privileges to modify files.

Directory Name Path (Local Install) Path (System Install) Comment
components ~/.local/share/flatpak/app/net.retrodeck.retrodeck/current/active/files/retrodeck/components/ /var/lib/flatpak/app/net.retrodeck.retrodeck/current/active/files/retrodeck/components/ RetroDECK components directory

7. Launch RetroDECK

Start RetroDECK after installation. If everything is configured correctly, RetroDECK will automatically detect and load the newly installed component.

If the component does not appear in the frontend, you may need to update the ES-DE custom configuration files to register the new component.

Configuration files:

retrodeck/ES-DE/custom_systems/es_find_rules.xml retrodeck/ES-DE/custom_systems/es_systems.xml

Add the appropriate entries to ensure the new component is properly defined and discoverable within ES-DE.


Creating a new componment_recipe.json tips


Tip 1: Component Source Format: What to Prioritize?

When multiple source formats are available for a component, prioritize them in the following order for ease of integration with RetroDECK:

Priority Format Description
1 Flatpak A sandboxed package format commonly used on Linux for app distribution , published on flathub
2 AppImage A portable, self-contained executable that runs without installation
3 Precompiled Binary A ready-to-run executable built for a specific platform
4 Build from Source Raw source code that must be compiled manually before use

Tip 2: Templates and Examples of component_recipe.json

On the wiki (linked next to this guide), you’ll find templates and example component_recipe.json files.
Use these as a baseline when creating a new recipe. More examples will be added over time.

You should also check the cooker components repository for the most up-to-date recipes to use as inspiration:

RetroDECK Components Repository (cooker branch)


Structure of component_recipe.json

All component_recipe.json contain at least four parts:

Name

  • The root key of the component_recipe.json file, indicating the component’s name.
  • The artifact name and some source paths (e.g., the directory name in the components repo) are derived from this name, so it should be consistent across the component.

Source

  • Each component has a single source from which files are pulled to be stored in the final artifact.

Asset

  • Every component source includes at least one asset-the file(s) pulled from the source ingredient.

Extras

  • Minimum extras: component launcher, component manifest, and shipped default config.
  • May also include prepared symlinks or other locally‑available files that do not come from downloaded sources.

Optional Inclusions

Additional Sources

  • Used when a component requires more than one download to gather all needed files, or when the original source is a nested archive requiring multiple extraction passes.

Additional Assets

  • Each source can have its own set of assets, directing the recipe to pull specific files from specific sources.

Libraries

  • Most sources need extra libraries to function within the base Flatpak environment.
  • The hunt_libraries.sh script can bootstrap a list of requirements for every binary.

Key Principles

  • Pin to a Release - All ingredients must be taken from a fixed release to preserve quality and avoid unpredictable changes.
  • Stable Versions List - The desired_versions.sh file enumerates all "stable" source versions. These can be referenced in component recipes as placeholders, reducing the need for frequent edits when a new stable version appears.

Example - Recipe Breakdown: Azahar

{
  "azahar": [
    {
      "source_url": "org.azahar_emu.Azahar",
      "source_type": "flatpak_id",
      "version": "$AZAHAR_DESIRED_VERSION",
      "dest": "user",
      "extraction_type": "flatpak",
      "assets": [
        {
          "type": "dir",
          "source": "bin",
          "dest": "bin"
        },
        {
          "type": "dir",
          "source": "$REPO_ROOT/$COMPONENT_NAME",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "create",
          "dest": "component_version",
          "contents": "$SOURCE_VERSION"
        },
        {
          "type": "dir",
          "source": "$REPO_ROOT/$COMPONENT_NAME/assets/rd_config",
          "dest": "rd_config"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_functions.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_launcher.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_manifest.json",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_recipe.json",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_prepare.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        }
      ],
      "libs": []
    }
  ]
}

Component Recipes: Component Information & Key‑Value Reference

Field Description
JSON root key Defines the component name and creates the placeholder variable $COMPONENT_NAME.
source_url {SOURCE_URL} - URL/path to download the source. Acceptable forms: direct HTTP(S) link, redirect, GitHub repo URL, flathub ID or local filesystem path. Can contain a {VERSION} placeholder that will be replaced by the value of the version key. Relative local paths expand to $WORKDIR/.
source_type {SOURCE_TYPE} - Determines which downloader plugin to use
• - flatpak-id - Flathub ID
- github-release - Github Releases
- http - Web download
version {VERSION} - Specific version to fetch. For non‑local sources, this replaces {VERSION} in source_url. For local sources, latest can be used if no version is required. Required for all types except local. Substituted for {VERSION} in source_url.
http / github-release - Specific version string (or latest for GitHub)
extraction_type {EXTRACTION_TYPE} - Extraction plugin to apply to the downloaded file. Supported methods:
appimage - Extract AppImage ($EXTRACTED_PATH = <dest>/<AppImage‑name>-extracted)
archive - Extract any archive ($EXTRACTED_PATH = <dest>/<archive‑name>-extracted)
local / git / flatpak - Dummy plugins returning $DOWNLOADED_FILE as $EXTRACTED_PATH
dest (Optional) Absolute destination for download/extraction. Defaults to $WORKDIR. For flatpak-id it also selects install scope (user / system).
additional_sources (Optional) Array of extra source objects with the same structure, allowing multiple downloads to be processed similarly.

assets

Items to copy from the extracted source into the final artifact.

Field Description
type Defines the kind of asset operation.

dir - Pull an entire directory
file - Pull a single file
symlink - Create a symbolic link
create - Create a file
archive - Create an archive
merge - Merge files
file-rename - Rename files
script - Run a bash script
source Path to the desired or created file, script, or directory,
relative to $EXTRACTED_PATH (from the extraction stage).
Example: usr/bin
dest Destination relative to $COMPONENT_ARTIFACT_ROOT for dir, file, and create.

For symlink, this is an absolute target path.
If a relative path is provided, it expands to:
$COMPONENT_ARTIFACT_ROOT/<dest>

For archive, specify the output archive type:
7z, zip, tar.gz, tgz, tar.bz2, tbz2, tar.xz, txz, tar
contents (Optional) Allows inserting provided content directly into the destination file.
For script, this can also define arguments such as --verbose.

libs

This section lists additional library objects, each processed identically to the library entries described earlier.

For guidance on generating a starting array automatically, refer to the library hunter documentation. It explains how to use hunt_libraries.sh to bootstrap your libs[] array.

Field Description
library Name of the library to collect.
Libraries are resolved by stripping the filename to its base extension to capture dynamic symlinks.
Example: specifying libQt6Widgets.so.6 gathers all matching files like libQt6Widgets.so* from the source.
runtime_name (Optional) Name of the Flatpak runtime from which to obtain the library.
Requires runtime_version.
runtime_version (Optional) Specific Flatpak runtime version to target.
Requires runtime_name.
dest Directory where the library should be placed,
relative to $COMPONENT_ARTIFACT_ROOT.

If a runtime is specified, expands to:
$COMPONENT_ARTIFACT_ROOT/<runtime_name>/<runtime_version>/

Otherwise expands to:
$COMPONENT_ARTIFACT_ROOT/

Most libraries should use shared-libs to support the decoupling features in the RetroDECK build process.
However, this depends on the application - some require libraries in lib or directly next to the binary.
source (Optional) Specifies a concrete source location for the library,
relative to $EXTRACTED_PATH when not using a runtime.
Used when the library must be taken from a specific asset rather than a Flatpak runtime.

\(REPO_ROOT/\)COMPONENT_NAME/assets/

This directory contains all custom, component-specific RetroDECK configuration files and assets that need to be included in the Flatpak environment.

Examples:

  • Component-specific RetroDECK pre-configured files located under $REPO_ROOT/$COMPONENT_NAME/assets/rd_config, ranging from individual files to organized subfolders.
  • Other assets required by the component.

For additional examples, see the components repo.


\(REPO_ROOT/\)COMPONENT_NAME/tmp_assets/

This directory stores component-specific temporary files and assets. Not all files in this directory are included in the final Flatpak. Only the files required by the recipe are used.

Examples:

  • Built from Source component artifacts compressed into a .tar.gz file, stored in $REPO_ROOT/$COMPONENT_NAME/tmp_assets/<component>.tar.gz for recipes that cannot fetch them from external sources.

For additional examples, see the components repo.


Guide: Adding Libraries - The Library Hunter

Use hunt_libraries.sh to automatically generate the libs[] array:

hunt_libraries.sh

Simply run the script against the binary you are integrating, and it will help identify the required libraries.

Note:
This is not a perfect solution, but it provides a solid starting point and can significantly speed up the process.


Best Practices While Hunting Libraries

It is recommended to have multiple GNOME and KDE Platform runtimes installed, as the hunter can resolve libraries directly from the corresponding runtime.

For older components, dependencies may require libraries from previous runtime versions. Rather than defining these manually, the hunter can automatically pull the correct versions from the appropriate runtime.

If the hunter cannot locate certain libraries, check whether they are included in the component’s native libraries and grab it from there.

In rare cases where a required library is not available via the component package or the found by the hunter:

  • Locate the library manually (from the web or your host system).
  • Include it as a tmp_asset in a compressed format.
  • Integrate it during the recipe process.

Nested Archives & additional_sources

  • A nested archive creates a new archive that also needs extraction.
  • Objects are processed in the order they appear in the recipe, allowing later sources to depend on earlier ones.

Simplified Example: Extracting a Nested Archive

{
  "retroarch": [
    {
      "source_url": "https://buildbot.libretro.com/stable/{VERSION}/linux/x86_64/RetroArch.7z",
      "source_type": "http",
      "version": "1.22.2",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores",
          "dest": "$WORKDIR/cores"
        },
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/overlays",
          "dest": "$WORKDIR/overlays"
        },
        {
          "type": "merge",
          "source": "$REPO_ROOT/$COMPONENT_NAME/assets/rd_extras/borders",
          "dest": "$WORKDIR/overlays/borders"
        },
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/assets",
          "dest": "assets"
        },
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/autoconfig",
          "dest": "autoconfig"
        },
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/database/cursors",
          "dest": "database/cursors"
        },
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/database/rdb",
          "dest": "database/rdb"
        },
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/filters",
          "dest": "filters"
        },
        {
          "type": "tar.gz",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/shaders/.",
          "dest": "rd_extras/shaders"
        },
        {
          "type": "dir",
          "source": "$REPO_ROOT/$COMPONENT_NAME/assets/rd_config",
          "dest": "rd_config"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/assets/rd_extras/ScummVM.zip",
          "dest": "rd_extras"
        },
        {
          "type": "create",
          "dest": "component_version",
          "contents": "$SOURCE_VERSION"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_functions.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_launcher.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_manifest.json",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_recipe.json",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_prepare.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        },
        {
          "type": "file",
          "source": "$REPO_ROOT/$COMPONENT_NAME/component_update.sh",
          "dest": "$COMPONENT_ARTIFACT_ROOT"
        }
      ],
      "libs": []
    },
    {
      "source_url": "$EXTRACTED_PATH/RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage",
      "source_type": "local",
      "extraction_type": "appimage",
      "assets": [
        {
          "type": "dir",
          "source": "usr/bin",
          "dest": "bin"
        }
      ]
    },
    {
      "source_url": "https://buildbot.libretro.com/stable/{VERSION}/linux/x86_64/RetroArch_cores.7z",
      "source_type": "http",
      "version": "1.22.2",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "merge",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores",
          "dest": "$WORKDIR/cores"
        }
      ]
    },
    {
      "source_url": "https://buildbot.libretro.com/{VERSION}/linux/x86_64/latest/citra_libretro.so.zip",
      "source_type": "http",
      "version": "nightly",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "file",
          "source": "citra_libretro.so",
          "dest": "$WORKDIR/cores"
        }
      ]
    },
    {
      "source_url": "https://buildbot.libretro.com/{VERSION}/linux/x86_64/latest/sameduck_libretro.so.zip",
      "source_type": "http",
      "version": "nightly",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "file",
          "source": "sameduck_libretro.so",
          "dest": "$WORKDIR/cores"
        }
      ]
    },
    {
      "source_url": "https://github.com/RapidEdwin08/Genesis-Plus-GX-Expanded-Rom-Size",
      "source_type": "git",
      "version": "latest",
      "dest": "Genesis-Plus-GX-Expanded-Rom-Size",
      "extraction_type": "local",
      "assets": [
        {
          "type": "file",
          "source": "builds/Linux_so64/genesis_plus_gx_libretro.so",
          "dest": "$WORKDIR/cores"
        }
      ]
    },
    {
      "source_url": "https://buildbot.libretro.com/{VERSION}/linux/x86_64/RetroArch_cores.7z",
      "source_type": "http",
      "version": "nightly",
      "dest": "nightly-cores",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "merge",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores",
          "dest": "$WORKDIR/cores"
        }
      ]
    },
    {
      "source_url": "https://github.com/libretro/libretro-database",
      "source_type": "git",
      "version": "latest",
      "extraction_type": "local",
      "assets": [
        {
          "type": "tar.gz",
          "source": "cht/.",
          "dest": "rd_extras/cheats"
        }
      ]
    },
    {
      "source_url": "http://bluemsx.msxblue.com/rel_download/blueMSXv{VERSION}full.zip",
      "source_type": "http",
      "version": "282",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "dir",
          "source": "Machines",
          "dest": "rd_extras/MSX/Machines"
        },
        {
          "type": "dir",
          "source": "Databases",
          "dest": "rd_extras/MSX/Databases"
        }
      ]
    },
    {
      "source_url": "https://github.com/rsn8887/capsimg/releases/download/{VERSION}/Capsimg_for_Retroarch.zip",
      "source_type": "github-release",
      "version": "1.1",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "file",
          "source": "Linux/x86-64/capsimg.so",
          "dest": "rd_extras/Amiga"
        }
      ]
    },
    {
      "source_url": "$WORKDIR",
      "source_type": "local",
      "extraction_type": "local",
      "assets": [
        {
          "type": "tar.gz",
          "source": "cores",
          "dest": "rd_extras/cores"
        }
      ]
    },
    {
      "source_url": "$WORKDIR",
      "source_type": "local",
      "extraction_type": "local",
      "assets": [
        {
          "type": "tar.gz",
          "source": "overlays/.",
          "dest": "rd_extras/overlays"
        }
      ]
    }
  ]
}

Explanation

  1. Core source - Downloads RetroArch.7z and extracts it as an archive.
  2. First additional source - Treats the already‑extracted AppImage (RetroArch-Linux-x86_64.AppImage) as a local source, extracts it, and copies its usr/bin directory to the artifact’s bin folder.
  3. Second additional source - Downloads a second archive (RetroArch_cores.7z), extracts it, and copies the cores directory into the artifact’s cores folder.

By ordering the additional sources array this way, the Alchemist ensures that each step has the necessary data from the previous step before proceeding.


Object 1 - Core Archive (downloaded)

{
  "source_url": "https://buildbot.libretro.com/stable/{VERSION}/linux/x86_64/RetroArch.7z",
  "source_type": "http",
  "version": "1.21.0",
  "extraction_type": "archive"
}

Alchemist:

  • Download: RetroArch.7z is fetched from the internet and placed into $WORKDIR.
  • Extraction: Treated as an archive; it is extracted to the default destination $WORKDIR/RetroArch.7z-extracted.
  • Post‑extract actions: None (no assets, libs, or extras).
  • Next step: The Alchemist proceeds to Object 2.

Object 2 - Local AppImage (extracted from the first archive)

    {
      "source_url": "https://buildbot.libretro.com/stable/{VERSION}/linux/x86_64/RetroArch_cores.7z",
      "source_type": "http",
      "version": "1.21.0",
      "extraction_type": "archive",
      "assets": [
        {
          "type": "dir",
          "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores",
          "dest": "cores"
        }
      ]
    }
  ]
}

Alchemist:

  • Source: The AppImage located at $WORKDIR/RetroArch.7z-extracted/RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage (produced by Object 1).
  • Extraction: Handled as an appimage.
  • Asset gathering: The directory $WORKDIR/$EXTRACTED_PATH/usr/bin/ is collected and copied to $COMPONENT_ARTIFACT_ROOT/bin/.

Object 3 - Additional Cores Archive (downloaded)

  • Download: A new archive RetroArch_cores.7z is retrieved from the internet.
  • Extraction: Treated as an archive.
  • Asset gathering: The path $WORKDIR/$EXTRACTED_PATH/RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores/ is collected and placed into $COMPONENT_ARTIFACT_ROOT/cores/.
{
    "source_url": "https://buildbot.libretro.com/stable/{VERSION}/linux/x86_64/RetroArch_cores.7z",
    "source_type": "http",
    "version": "1.21.0",
    "extraction_type": "archive",
    "assets": [
        {
            "type": "dir",
            "source": "RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores",
            "dest": "cores"
        }
    ]
}

Why This Verbose Multi‑Object Approach?

  • Fine‑grained control: Each object can specify its own assets, libraries, and extras, ensuring precise handling of files.
  • Avoids conflicts: Prevents issues where a parent archive contains multiple files with the same extensions (blob‑matching problems).
  • Flexibility: Different classes of files (assets, libs, etc.) can originate from distinct sources, allowing consistent and reproducible builds.

By processing each source object sequentially, the Alchemist maintains strict control over every step, guaranteeing deterministic results across builds.


Reusable Environmental Variable Reference

Core Paths

Variable Description
$REPO_ROOT Set to the root of the git-cloned repository if alchemist.sh is invoked inside one.
Otherwise defaults to the directory from which the script is called.
$WORKDIR Working directory for the current component build.
Holds downloaded sources, extracted files, and the temporary artifact directory.
Can be overridden via an argument to alchemist.sh.
Otherwise falls back to $DEFAULT_WORKDIR defined in defaults.sh.
$COMPONENT_NAME Name of the component currently being processed.
Should match the component directory name in the components repository for consistency.
$COMPONENT_ARTIFACT_ROOT Path to the final artifact directory where all files destined for the archive are placed.
Computed as:
$WORKDIR/$COMPONENT_NAME-artifact

Download & Extraction Helpers

Variable Description
$DOWNLOADED_FILE Full path of the most recently downloaded file.
Populated by the download.sh plugin via:
echo "DOWNLOADED_FILE=..."
$EXTRACTED_PATH Full path of the most recently extracted archive.
Populated by the extract.sh plugin via:
echo "EXTRACTED_PATH=..."

For local extractions (no real archive), a dummy plugin returns the same path as $DOWNLOADED_FILE.

Variable Description
$FLATPAK_USER_ROOT Default user install location:
$HOME/.local/share/flatpak/app
Defined in defaults.sh.
$FLATPAK_SYSTEM_ROOT Default system install location:
/var/lib/flatpak/app
Defined in defaults.sh.
$FLATPAK_DEFAULT_INSTALL_MODE Default install mode for Flatpak packages:
user
System mode may require sudo.
$FLATHUB_REPO URL of the Flathub repository:
https://flathub.org/repo/flathub.flatpakrepo
Adjust if the repository location changes.

Version Management

Variable Description
$DESIRED_VERSIONS Path to the desired_versions.sh script containing the catalog of desired component versions.
Used to resolve version placeholders in component recipes.
Can be overridden per alchemist.sh run via an input argument,
allowing separate stable and beta version sets.

Alchemist Execution Logic

Take the Azahar example for above:

  1. Component Name - Set to azahar.
  2. Download URL - org.azahar_emu.Azahar.
  3. Downloader Plugin - flatpak_id (selected via source_type).
  4. Version Resolution - $AZAHAR_DESIRED_VERSION is read from desired_versions.sh (e.g., export AZAHAR_DESIRED_VERSION="2123.3"). This value replaces {VERSION} in the URL.
  5. Downloaded File Path - Stored in $DOWNLOADED_FILE.
  6. Extraction Plugin - flatpak, applied to $DOWNLOADED_FILE.
  7. Extracted Destination - Path returned in $EXTRACTED_PATH.
  8. Copy the full directory from $EXTRACTED_PATH/usr/bin to $COMPONENT_ARTIFACT_ROOT/bin.
  9. Flatpak Runtime - Install the required runtime (name and version) if it isn’t already present.
  10. Gather Library - Retrieve libQt6Widgets.so.6 from the specified Flatpak runtime and place it in the appropriate location within the artifact.

Alchemist Process Abstraction

At a high level, the Alchemist processes information in this loop:

  1. Read component_recipe.json file.
  2. Read component name from the root key.
  3. Generate a set of parent objects to be processed.
  4. Each parent object contains download sources, extraction commands, asset‑gathering instructions, library‑gathering instructions, and extras‑gathering instructions.
  5. Process each object sequentially.
  6. Compress the contents of the *-artifact directory for storage.

Example: Final Artifact Layout ($COMPONENT_NAME-artifact) for Azahar

azahar-artifact
├── bin
│   ├── azahar
│   └── qt.conf
├── component_extras.sh
├── component_functions.sh
├── component_launcher.sh
├── component_libs.json
├── component_manifest.json
├── component_prepare.sh
├── component_recipe.json
└── assets
    └── rd_config
        └── qt-config.ini