Skip to content

Content pak reference

This page is the short authoring reference for content-paks-v1. See Adding a system or emulator for a walkthrough and the public normative contract for every rejection reason, default, merge rule, and effective-catalog detail.

pak.json becomes a content manifest when it has a top-level provides object:

{
"name": "Example",
"platform": "mlp1",
"pak_version": "1.0.0",
"min_leaf_version": "0.11.0",
"provides": {
"schema": 1,
"systems": [],
"system_extensions": [],
"cores": []
}
}

At least one of the three arrays must be non-empty. schema is exactly 1. Unknown fields inside provides and its entries are refused rather than ignored. Other top-level pak.json metadata is allowed; content_scrape is one such optional companion.

An executable launch.sh controls whether the installed pak appears in Apps:

launch.shprovidesResult
yesnoordinary app
yesyesapp plus content contribution
noyescontent only; hidden from Apps
nonoinvalid package
FieldRequiredValue
idyes^[A-Z0-9_]{2,32}$
nameyes1-64 characters
patternsyes1-32 recognized ROM-folder names
extensionsyes1-64 lowercase extensions, without dots
default_coreyescore id available after merge
rom_rootyesRoms/<folder>
image_rootyesImages/<folder>
icon_flatyespak-relative existing PNG
icon_photographicnopak-relative existing PNG or null
archive_extensionsnoarchive extensions accepted directly
archive_inner_extensionsnoROM extensions recognized inside archives
archive_modenopass_through, extract, or none
file_namesnoexact filenames that identify content
ignore_file_namesnoexact filenames discovery ignores
playlist_extensionsnoplaylist extensions such as m3u
m3u_generationnonone, auto, or manual
alternate_coresnoadditional core ids for this new system
bios_notesnoup to eight short BIOS requirements
screenscraper_platform_idsnoup to eight integers from 1-99999
groupnoCentral Scrutinizer group, or null
bios_directorynoone FAT32-safe directory component, or null

Defaults and exact length limits live in the normative contract and schema.

Every core has id, display_name, and type. Core ids match ^[a-z0-9_]{2,64}$.

For type: "retroarch":

FieldRequiredValue
libretro_nameyeslibretro core name
file_nameyespak-relative core binary
info_nameyespak-relative .info file
config_folderyesFAT32-safe Saves/States directory component

For type: "path":

FieldRequiredValue
pathyespak-relative existing executable

Both types may declare boolean supports_menu, supports_savestate, supports_disk_control, and needs_swap; each defaults to false.

The fields requires_direct_drm, legacy_flat_core, name_map, and status are forbidden.

This is the only supported way to add an alternate core to an existing system:

{
"system_id": "SFC",
"add_alternate_cores": ["my_snes_core"]
}

It has exactly those two fields. It cannot override a system’s name, folders, art, extensions, or default core.

Every declared file path is relative to the pak root and must:

  • not begin with /;
  • contain no .. component;
  • remain inside the pak after resolving every symlink component;
  • exist as a regular file;
  • be executable when it is a standalone path core.

Do not persist an SD-card mount point in a manifest. Leaf resolves the provider pak at runtime so /mnt/sdcard and /media/sdcard1 swaps remain safe.

Ownership is case-insensitively unique across system ids, patterns, ROM roots, image roots, core ids, config folders, and materialized .info filenames.

  • A collision with Leaf refuses that contribution.
  • A collision between two paks refuses both; directory order never chooses a winner.
  • Refusing a default core also refuses the system that depends on it.
  • A missing extension target is dropped and diagnosed.
  • A missing alternate core name is dropped while the rest of the extension can remain.

Diagnostics are written to .umrk/<platform>/catalog/diagnostics.json and shown on the installed pak’s Pak Rat detail page.

A package that declares provides belongs in the storefront’s content[] lane, even when it is a hybrid with launch.sh. Its pakrat.json uses "kind": "content", targets a concrete platform, and gates every published version with min_leaf_version. The same id must never appear in both apps[] and content[].

Use the ScummVM-pak repository as the build, licence, Pak Rat metadata, and CI reference.