Pupdate - A thing for updating your Analogue Pocket
See the codeA free utility for updating openFPGA cores, firmware, and related assets on your Analogue Pocket. It can run as an interactive console menu or from the command line.
A browsable list of available cores is here: openFPGA cores inventory.
Please use the latest release before reporting issues; older builds are not supported.
Do not clone the repo if you only want to run the tool. Download the latest release, unzip it, place the executable for your OS on the root of your SD card (or another folder you use as the install path), and run it.
Use Settings from the main menu to walk through toggles, or edit pupdate_settings.json for advanced options. In the full-screen UI (--tui) the same options live on the Settings tab, grouped — see Settings.
In most macOS default installation setups, you will likely encounter issues running the script the "easy way". The following command will remove the quarantine from the pupdate script only. ⚠️ Use sparingly ⚠️
xattr -d com.apple.quarantine /path/to/pupdate
The full menu tree is documented in MENU.md.
| Area | What it covers |
|---|---|
| Cores | Downloads and updates openFPGA cores from the library inventory; optional local inventory files; per-core skip, assets, rename, display modes, extras, and version pinning |
| Firmware | Checks for and installs Analogue Pocket firmware |
| Assets | ROMs, BIOS, and other files from configured archives (archive.org, custom, core-specific) |
| Pocket setup | Display modes, image packs, library images, Game Boy palettes, instance JSON (e.g. PC Engine CD), Game & Watch ROM build flow, Super GameBoy aspect ratio, Analogizer config, Patreon Config (email, Patreon session cookie for JT beta auto-fetch, cookie test), Directory Locations (backup saves path, archive cache, temp directory), GitHub token (API rate limits), debug helpers |
| Maintenance | Update/install/reinstall/uninstall cores, ROM set archives, prune save states, clear archive cache, pin/unpin core versions, validate/repair core JSON |
| Extras | Pocket Extras (additional assets, combination platforms, variant cores) from pocket_extras.json |
| Plugins | Plugins for custom functionality |
Update All · Update Firmware · Select Cores · Download Assets · Backup Saves & Memories · Pocket Setup · Pocket Maintenance · Pocket Extras · Plugins · Pin / unpin core version · Settings · Additional settings · Asset archives · CLI · Jotego beta · Analogizer · Troubleshooting · Developers
The “do everything” option. Steps marked with * follow your Settings toggles.
Pinned versions: If a core has pinned_version set in settings, the updater resolves that version from the inventory release list only. If the pin does not match any listed release, that core is skipped with a message and the run continues.
(Pocket Maintenance) — Pick installed cores to update.
(Pocket Maintenance) — Pick cores you do not have installed yet; installs them without running a full Update All.
Checks for Pocket firmware updates only, then exits.
Asks how new cores should be handled:
Fetches missing assets (ROMs, BIOS, etc.) for selected cores from your configured archives.
You supply your own ROMs for non-arcade cores where the archive does not provide them.
Zips the Pocket Saves and Memories folders to the path in settings (default: Backups next to the executable unless overridden).
display_modes.json to the cores that reference those modes.To override the hosted display_modes.json, place a copy next to the executable and set use_local_display_modes to true.
Lists image packs (from image_packs.json), downloads and extracts to Platforms/_images.
Library_Image_Set_v1.0.zip from your configured archive.pocket_library_images.json (bundled next to the executable), same idea as Pocket Extras. Each group has a menu_title (submenu label) and entries with menu_label, id, github_user, github_repository, and sources: an array of release_asset (zip on the release), path_under_extract (folder path inside that zip to .bin files, /-separated), and dest_images_subfolder (under System/Library/Images/ on the device). Optional post_install_note is printed after a successful install (when any files were copied). Enable Use a local pocket_library_images.json file in Settings to read only the local copy instead of fetching the catalog from GitHub (see use_local_pocket_library_images in pupdate_settings.json).CLI (like pocket-extras): pocket-library-images alone installs Spiritualized. pocket-library-images -l lists catalog entry id values; -n <id> installs that entry; -n <id> -i prints details. Example: pocket-library-images -n codewario_boxarts.
Downloads palette packs maintained by davewongillies and others (see original palette credits in prior releases); large collection of official and community palettes.
/Assets/{platform}/common, one game per folder (full game title as folder name).common and builds launch JSONs.build_instance_jsons: false in settings.ignore_instance.json with use_local_ignore_instance_json if you maintain exclusions.Create:
/Assets/gameandwatch/agg23.GameAndWatch/artwork/Assets/gameandwatch/agg23.GameAndWatch/romsPut [game].zip in each; run the menu item to build. Game & Watch asset downloads are configured under archives (core-specific archive for agg23.GameAndWatch)—enable/configure there rather than a separate global toggle.
Apply 8:7 to chosen Spiritualized.SuperGB* cores, or restore 4:3.
Jotego vs Standard wizards for Analogizer JSON. See Analogizer setup.
Submenu under Pocket Setup.
session_id cookie for experimental Patreon-based jtbeta.zip auto-fetch. See Jotego beta for full steps and caveats.Submenu under Pocket Setup.
Backups is a relative path (resolved from the process current directory when the tool runs; use an absolute path if you need a fixed location). Clearing the value when prompted resets to Backups. Same as config.backup_saves_location in JSON.pupdate\cache (Windows) / equivalent. Leave empty (or save an empty line) to use that default. Same as config.archive_cache_location.Path.GetTempPath()). Same as config.temp_directory.Stores a personal access token for GitHub API calls (higher rate limits than anonymous requests). The current value is shown when you open this item. You can also set config.github_token in pupdate_settings.json.
Prints a summary of platform categories and cores (debug / reference).
romsets.json).For installed cores with a GitHub-backed inventory entry:
metadata.version value in the inventory’s releases array for updates to succeed.Update behavior: The pinned ZIP URL is taken only from the inventory release that matches the pin (with simple v prefix normalization). There is no GitHub API fallback for pins. If the pin is missing from releases, the core is skipped for that run with a clear message.
Third-party bundles defined in pocket_extras.json. Each entry can show a description and links before install (show_menu_descriptions in settings); the --tui Extras tab shows them in an Install / Cancel dialog.
Exact menu labels are built at runtime; see MENU.md for a current snapshot.
Pupdate can install and run plugins distributed as GitHub repos. Each plugin is a small program that can drive its own interactive flow inside pupdate. To install ROM packs, configure something on your Pocket, fetch external content, etc.
Pocket Extras → Plugins → Install from GitHub... and paste either:
owner/repo, orhttps://github.com/owner/repopupdate downloads the latest release of that repo. Example to try: openfpga-library/pocket-plugin.
After installing, the plugin appears in the same Pocket Extras → Plugins menu by its name. Select it and follow its prompts. Pick Cancel at any prompt to stop the plugin.
See openfpga-library/pocket-plugin for the plugin contract, sample code, and release format. Distribute your plugin as a GitHub release that includes plugin.wasm and plugin.json as release assets. The release tag becomes the version pupdate uses for update checks.
In the full-screen UI (--tui), ↑/↓ stay inside the current list, ←/→ switch tabs, and
A–G jump straight to one. Those single-key shortcuts stand down while a text box has focus,
so the Cores tab's Filter box takes every key - press / from the core table to jump into
it and Esc to clear it.
Toggles exposed in the Settings menu (stored in pupdate_settings.json):
| Name | Description |
|---|---|
| Download Firmware Updates | Firmware check during Update All |
| Download Missing Assets | Asset check during Update All |
| Only check assets for cores updated during 'Update All' | Skip the asset check for cores that are already up to date; only updated/installed cores get their assets checked |
| Build game JSON Files | Instance JSON builder during Update All |
| Delete cores, not managed by pupdate | Remove unmanaged cores from SD when enabled |
| Automatically rename Jotego cores | Friendly platform names after install |
| Use CRC check | Verify assets by CRC; re-download if mismatch |
| Preserve Platforms folder | Avoid overwriting Platforms on Update All |
| Skip alternative ROMs | Ignore _alternatives folders when fetching assets (default on) |
| Compress and backup Saves and Memories | Backup during Update All |
| Show Menu Descriptions | Prompts/descriptions for Pocket Extras and similar |
| Use custom archive | Use the preconfigured “custom” archive entry instead of default archive.org |
| Automatically install updates to Pupdate | Self-update without prompt on startup |
| Use Local Pocket Extras | Use local pocket_extras.json |
| Use Local Display Modes | Use local display_modes.json |
| Cache downloaded archive files locally | Keep a reusable cache; optional cache path in JSON |
| Adds a description element to the video.json display modes | Non-breaking extra field in generated video JSON |
| Hide and uninstall Analogizer core variants | Hides Analogizer-specific core variants |
| Hide and uninstall AI-generated cores (Experimental) | Hides and (during Update All) uninstalls cores whose AI score exceeds your threshold. Toggle this on, then set the cutoff with Settings → Set AI Filter Threshold (see AI-generated core filter). Cores not included in the report are left alone. |
| Download files in concurrent chunks | Splits downloads into parallel HTTP range requests for faster transfers on bandwidth-limited servers like archive.org; falls back to a single connection when the server doesn't support ranges (default on). Tune the parallelism with config.download_chunk_count |
Game & Watch (and other core-specific archives) are enabled in the archives array in JSON, not via a separate Settings row.
Edit pupdate_settings.json for keys that are not bool menu toggles:
| Name | Description |
|---|---|
config.github_token | Used for GitHub API calls (rate limits); also settable under Pocket Setup → Set GitHub Token (classic) or Settings → Accounts → GitHub token (--tui) |
config.download_new_cores | yes / no / ask — set by Select Cores |
config.display_modes_option | merge / overwrite / ask; Pocket Setup → Manage Display Modes → Change Display Modes Option Setting (classic) or Settings → Display Modes → Merge or overwrite default (--tui) |
config.backup_saves_location | Backup output directory; Pocket Setup → Directory Locations → Set Backup Saves Location (classic) or Settings → Update All → Backup saves location (--tui) |
config.temp_directory | Override temp extract path (default: OS temp); Pocket Setup → Directory Locations → Set Temp Directory (classic) or Settings → Assets & Downloads → Temp directory (--tui) |
config.archive_cache_location | Override archive cache directory when caching is on; Pocket Setup → Directory Locations → Set Archive Cache Location (classic) or Settings → Assets & Downloads → Archive cache location (--tui) |
config.download_chunk_count | Number of parallel HTTP range chunks when Download files in concurrent chunks is on (default 4); ignored for files under 1 MB or servers without range support |
config.ai_core_threshold | Percentage 0–100 for the Hide and uninstall AI-generated cores filter; cores scoring over this value are hidden and uninstalled (defaults to 100, so no cores will ever be marked by default). Set via Settings → Set AI Filter Threshold (classic) or Settings → Core Filtering → AI score threshold (--tui) |
config.suppress_already_installed | Reduce “already installed” console noise |
config.use_local_cores_inventory | Use local cores.json and platforms.json (openFPGA Library v3 format) next to the executable |
config.use_local_blacklist | Use local blacklist.json instead of downloading |
config.use_local_image_packs | Use local image_packs.json |
config.use_local_ignore_instance_json | Use local ignore_instance.json |
archives | Archive definitions: internet_archive, custom_archive, core_specific_archive, core_specific_custom_archive (see below) |
credentials.internet_archive | Optional archive.org username/password |
core_settings.<core_id>.* | Per core: skip, download_assets, platform_rename, pocket_extras, pocket_extras_version, display_modes, original_display_modes, selected_display_modes, requires_license, pinned_version |
blacklist.json lists filenames not downloaded as assets. Entries support * and ? wildcards; matching applies to the full slot path and to the file name alone (useful for paths like subfolder/game.bin).
pupdate can mark or filter out cores that appear to be AI-generated, using the openFPGA AI check report built by neil-morrison44. Each core is given a score from 0 to 1. The closer to 1, the more likely it is to be AI generated.
How the score is calculated: An automated tool (openfpga-library/openfpga-ai-check) regularly looks through each core's public development history for signs that AI tools were used. For example, how often "co-authored by Claude" appears in commit messages. The more signs detected, the higher the score. A core that looks entirely AI made scores near 1, one that only had occasional AI help scores lower. Older cores from before AI tools were common are given a 0. Keep in mind this is an educated guess and it can be inaccurate. Core devs will be able to submit requests to fix incorrect detections. Use at your own risk (the risk really just being you will have some cores hidden from you with false positives)
--tui) - a percentage (0–100, defaults to 100). Cores that score over the threshold are labeled or hidden. Example: a threshold of 50 targets cores scoring above 0.50.100 to turn everything off (nothing scores above 1.0), including the labels.--tui), the Cores tab's details popup (Enter, or click [view]) shows the full report for that core: its score against your threshold, each individual check with the evidence it recorded (e.g. "Of the last 100 commit messages 97 mention Claude"), and when it was last analyzed. Cores missing from the report show as not scored.The archives array in pupdate_settings.json defines where assets come from. Stock config includes a default archive.org archive and a Retrodriven custom archive; you can switch via Use custom archive or edit JSON.
Types
internet_archive — name, archive_name (archive.org identifier).custom_archive — name, url, index (index format per archive.org JSON API).core_specific_archive — Same as internet_archive but scoped to one core name; optional file_extensions or files (not both); optional one_time.core_specific_custom_archive — Like core-specific but with url + index.Example core_specific_archive:
{
"name": "Spiritualized.2600",
"type": "core_specific_archive",
"archive_name": "htgdb-gamepacks",
"files": [
"@Atari 2600 2021-04-06.zip"
],
"enabled": true,
"one_time": true
}
Some items need login. Add to pupdate_settings.json:
"credentials": {
"internet_archive": {
"username": "me@something.com",
"password": "12345"
}
}
menu Interactive main menu (default)
-p, --path Absolute path to Pocket install / SD root
-s, --skip-update Open menu without checking for pupdate self-update
fund List sponsor / funding links
-p, --path
-c, --core Optional core id filter
update Run Update All (respects settings)
-p, --path
-c, --core Optional single core id
-r, --clean Clean reinstall cores
-u, --updated-assets-only Only check/download assets for cores updated this run
-y, --yes Non-interactive: assume defaults for all prompts (CI/cron)
uninstall Remove a core
-p, --path
-c, --core Required
-a, --assets Also remove Assets/{platform}/{core}
assets Download assets only
-p, --path
-c, --core Optional core id
firmware Check firmware
-p, --path
images Download a platform image pack
-p, --path
-o, --owner Repo owner
-i, --imagepack Repo name
-v, --variant Optional variant
instance-generator Run instance JSON generation (PC Engine CD workflow)
-p, --path
backup-saves Backup Saves & Memories
-p, --path
-l, --location Backup folder (required)
-s, --save Persist location in config for Update All
gameboy-palettes Download Game Boy palette pack
-p, --path
pocket-library-images Download Pocket library images
-p, --path
-n, --name Catalog entry id (omit for Spiritualized archive)
-i, --info Show details for -n
-l, --list List catalog ids (Spiritualized = no -n)
pocket-extras Install a Pocket Extra by id
-p, --path
-n, --name Extra id (required for install)
-i, --info Show details for name
-l, --list List all extras
display-modes Apply **recommended** display modes (same as curated menu action)
-p, --path
prune-memories Prune old save states (Memories)
-p, --path
-c, --core Optional core id
analogizer-setup Run Analogizer setup wizard
-p, --path
-j, --jotego Jotego-specific wizard
clear-archive-cache Clear cached archive downloads (same as Pocket Maintenance → Clear Archive Cache)
-p, --path
-y, --yes Required confirmation flag
validate-cores Check installed cores for missing or invalid JSON
-p, --path
-f, --fix Reinstall (clean) any cores with missing or invalid JSON
update-self Check for pupdate updates
help Help for a verb
version Print version
Non-interactive use (-y / --yes): a global flag. With it, pupdate assumes the default/affirmative answer to every prompt (install new cores, display modes, etc.) and skips the self-update prompt, so it can run unattended (CI, cron, containers). pupdate also returns a non-zero exit code when an update fails or an unhandled error occurs, so scripts can detect failures.
Examples
pupdate -p /path/to/sdcard/
pupdate update -c boogermann.bankpanic
pupdate update -p /path/to/sdcard/ --yes # unattended; non-zero exit on failure
pupdate assets -c jotego.jtcontra
pupdate images -i pocket-platform-images -o dyreschlock -v home
pupdate validate-cores
pupdate validate-cores --fix
Place jtbeta.zip from Patreon on the root of the SD card (exact name). Update All copies the beta key into the folders that need it. Do not rename the file.
jtbeta.zip (optional)Pupdate can download the latest jtbeta.zip for you. Manual placement (putting jtbeta.zip on the SD root yourself) always wins — auto-fetch only runs when no manual key is present. Two optional sources are supported; if both are enabled, GitHub is tried first and Patreon is the fallback.
Option A — GitHub (recommended):
Jotego distributes jtbeta.zip via a private GitHub repo (JTFPGA/jtbeta). Per Jotego's own Beta Files FAQ, access is granted to GitHub Sponsors of Jotego — and since Jotego's GitHub Sponsors page accepts Patreon as a payment route, existing Patreon patrons can get the same sponsor status (and therefore the repo invite) by linking their Patreon to their GitHub account.
JTFPGA/jtbeta once it arrives.repo scope, or a fine-grained PAT with Contents: Read on JTFPGA/jtbeta).github_token in pupdate_settings.json to that PAT.--tui).Option B — Patreon session cookie (experimental, fallback):
Experimental and flaky. This uses Patreon's undocumented frontend API with your browser session cookie, not a supported public API. Cookies expire (usually in weeks, sooner if you log out or clear cookies), and Patreon can change response field names without notice. Prefer Option A if you have any way to. Treat this as a best-effort fallback, not a stable integration.
pupdate will never use your Patreon session cookie for anything other than making HTTP requests to
patreon.comto locate and downloadjtbeta.zip(and, if you run the diagnostic, to verify your login and Jotego membership). It's stored locally inpupdate_settings.jsonand is never sent to any third party, telemetry endpoint, or server that isn'tpatreon.com.
https://www.patreon.com.session_id cookie.--tui), paste the value.--tui).Use Pocket Setup → Patreon Config → Test Patreon Session Cookie (Settings → Accounts → Test Patreon session cookie in --tui) to verify the cookie works and whether your account is currently a Jotego patron.
Notes:
jtbeta.zip on the SD root manually.Pocket Setup → Analogizer Config — choose Standard (RndMnkIII) or Jotego flow. For problems with generated files, ask the core author. Supported cores.
archives.Error in framework RS: bridge not responding — Run pupdate on a local disk, then copy results to the SD card.Missing ROM ID [1] in _alternatives — Turn off “Skip alternative ROMs” if you need those files installed.releases list.config.github_token in pupdate_settings.json.Failure processing application bundle / Default extraction directory ... is not accessible — Happens when running in a container (or any environment) where $HOME points to a directory that does not exist or is not writable. Either set DOTNET_BUNDLE_EXTRACT_BASE_DIR (or HOME) to a writable path, or download pupdate_linux_container*.zip from the release instead of pupdate_linux*.zip. The container variant places the native libs next to the binary so no runtime extraction is needed. Extract the whole archive and run pupdate from there.dotnet restore, dotnet build, dotnet run --project pupdate.csproj -- [verb] [options].src/Program.cs, src/partials/, src/services/, src/models/, src/options/, src/tui/ (the --tui interface).openfpga-cores-inventory / analogue-pocket
Thanks to neil-morrison44 — this project builds on his original script.
With special thanks to
Michael Hallett · RetroDriven · dyreschlock · espiox
30,138 followers · starred Aug 2022
17,025 followers · starred Feb 2023
1,573 followers · starred Nov 2022
259 followers · starred Mar 2025
Pupdate - A thing for updating your Analogue Pocket
See the codeA free utility for updating openFPGA cores, firmware, and related assets on your Analogue Pocket. It can run as an interactive console menu or from the command line.
A browsable list of available cores is here: openFPGA cores inventory.
Please use the latest release before reporting issues; older builds are not supported.
Do not clone the repo if you only want to run the tool. Download the latest release, unzip it, place the executable for your OS on the root of your SD card (or another folder you use as the install path), and run it.
Use Settings from the main menu to walk through toggles, or edit pupdate_settings.json for advanced options. In the full-screen UI (--tui) the same options live on the Settings tab, grouped — see Settings.
In most macOS default installation setups, you will likely encounter issues running the script the "easy way". The following command will remove the quarantine from the pupdate script only. ⚠️ Use sparingly ⚠️
xattr -d com.apple.quarantine /path/to/pupdate
The full menu tree is documented in MENU.md.
| Area | What it covers |
|---|---|
| Cores | Downloads and updates openFPGA cores from the library inventory; optional local inventory files; per-core skip, assets, rename, display modes, extras, and version pinning |
| Firmware | Checks for and installs Analogue Pocket firmware |
| Assets | ROMs, BIOS, and other files from configured archives (archive.org, custom, core-specific) |
| Pocket setup | Display modes, image packs, library images, Game Boy palettes, instance JSON (e.g. PC Engine CD), Game & Watch ROM build flow, Super GameBoy aspect ratio, Analogizer config, Patreon Config (email, Patreon session cookie for JT beta auto-fetch, cookie test), Directory Locations (backup saves path, archive cache, temp directory), GitHub token (API rate limits), debug helpers |
| Maintenance | Update/install/reinstall/uninstall cores, ROM set archives, prune save states, clear archive cache, pin/unpin core versions, validate/repair core JSON |
| Extras | Pocket Extras (additional assets, combination platforms, variant cores) from pocket_extras.json |
| Plugins | Plugins for custom functionality |
Update All · Update Firmware · Select Cores · Download Assets · Backup Saves & Memories · Pocket Setup · Pocket Maintenance · Pocket Extras · Plugins · Pin / unpin core version · Settings · Additional settings · Asset archives · CLI · Jotego beta · Analogizer · Troubleshooting · Developers
The “do everything” option. Steps marked with * follow your Settings toggles.
Pinned versions: If a core has pinned_version set in settings, the updater resolves that version from the inventory release list only. If the pin does not match any listed release, that core is skipped with a message and the run continues.
(Pocket Maintenance) — Pick installed cores to update.
(Pocket Maintenance) — Pick cores you do not have installed yet; installs them without running a full Update All.
Checks for Pocket firmware updates only, then exits.
Asks how new cores should be handled:
Fetches missing assets (ROMs, BIOS, etc.) for selected cores from your configured archives.
You supply your own ROMs for non-arcade cores where the archive does not provide them.
Zips the Pocket Saves and Memories folders to the path in settings (default: Backups next to the executable unless overridden).
display_modes.json to the cores that reference those modes.To override the hosted display_modes.json, place a copy next to the executable and set use_local_display_modes to true.
Lists image packs (from image_packs.json), downloads and extracts to Platforms/_images.
Library_Image_Set_v1.0.zip from your configured archive.pocket_library_images.json (bundled next to the executable), same idea as Pocket Extras. Each group has a menu_title (submenu label) and entries with menu_label, id, github_user, github_repository, and sources: an array of release_asset (zip on the release), path_under_extract (folder path inside that zip to .bin files, /-separated), and dest_images_subfolder (under System/Library/Images/ on the device). Optional post_install_note is printed after a successful install (when any files were copied). Enable Use a local pocket_library_images.json file in Settings to read only the local copy instead of fetching the catalog from GitHub (see use_local_pocket_library_images in pupdate_settings.json).CLI (like pocket-extras): pocket-library-images alone installs Spiritualized. pocket-library-images -l lists catalog entry id values; -n <id> installs that entry; -n <id> -i prints details. Example: pocket-library-images -n codewario_boxarts.
Downloads palette packs maintained by davewongillies and others (see original palette credits in prior releases); large collection of official and community palettes.
/Assets/{platform}/common, one game per folder (full game title as folder name).common and builds launch JSONs.build_instance_jsons: false in settings.ignore_instance.json with use_local_ignore_instance_json if you maintain exclusions.Create:
/Assets/gameandwatch/agg23.GameAndWatch/artwork/Assets/gameandwatch/agg23.GameAndWatch/romsPut [game].zip in each; run the menu item to build. Game & Watch asset downloads are configured under archives (core-specific archive for agg23.GameAndWatch)—enable/configure there rather than a separate global toggle.
Apply 8:7 to chosen Spiritualized.SuperGB* cores, or restore 4:3.
Jotego vs Standard wizards for Analogizer JSON. See Analogizer setup.
Submenu under Pocket Setup.
session_id cookie for experimental Patreon-based jtbeta.zip auto-fetch. See Jotego beta for full steps and caveats.Submenu under Pocket Setup.
Backups is a relative path (resolved from the process current directory when the tool runs; use an absolute path if you need a fixed location). Clearing the value when prompted resets to Backups. Same as config.backup_saves_location in JSON.pupdate\cache (Windows) / equivalent. Leave empty (or save an empty line) to use that default. Same as config.archive_cache_location.Path.GetTempPath()). Same as config.temp_directory.Stores a personal access token for GitHub API calls (higher rate limits than anonymous requests). The current value is shown when you open this item. You can also set config.github_token in pupdate_settings.json.
Prints a summary of platform categories and cores (debug / reference).
romsets.json).For installed cores with a GitHub-backed inventory entry:
metadata.version value in the inventory’s releases array for updates to succeed.Update behavior: The pinned ZIP URL is taken only from the inventory release that matches the pin (with simple v prefix normalization). There is no GitHub API fallback for pins. If the pin is missing from releases, the core is skipped for that run with a clear message.
Third-party bundles defined in pocket_extras.json. Each entry can show a description and links before install (show_menu_descriptions in settings); the --tui Extras tab shows them in an Install / Cancel dialog.
Exact menu labels are built at runtime; see MENU.md for a current snapshot.
Pupdate can install and run plugins distributed as GitHub repos. Each plugin is a small program that can drive its own interactive flow inside pupdate. To install ROM packs, configure something on your Pocket, fetch external content, etc.
Pocket Extras → Plugins → Install from GitHub... and paste either:
owner/repo, orhttps://github.com/owner/repopupdate downloads the latest release of that repo. Example to try: openfpga-library/pocket-plugin.
After installing, the plugin appears in the same Pocket Extras → Plugins menu by its name. Select it and follow its prompts. Pick Cancel at any prompt to stop the plugin.
See openfpga-library/pocket-plugin for the plugin contract, sample code, and release format. Distribute your plugin as a GitHub release that includes plugin.wasm and plugin.json as release assets. The release tag becomes the version pupdate uses for update checks.
In the full-screen UI (--tui), ↑/↓ stay inside the current list, ←/→ switch tabs, and
A–G jump straight to one. Those single-key shortcuts stand down while a text box has focus,
so the Cores tab's Filter box takes every key - press / from the core table to jump into
it and Esc to clear it.
Toggles exposed in the Settings menu (stored in pupdate_settings.json):
| Name | Description |
|---|---|
| Download Firmware Updates | Firmware check during Update All |
| Download Missing Assets | Asset check during Update All |
| Only check assets for cores updated during 'Update All' | Skip the asset check for cores that are already up to date; only updated/installed cores get their assets checked |
| Build game JSON Files | Instance JSON builder during Update All |
| Delete cores, not managed by pupdate | Remove unmanaged cores from SD when enabled |
| Automatically rename Jotego cores | Friendly platform names after install |
| Use CRC check | Verify assets by CRC; re-download if mismatch |
| Preserve Platforms folder | Avoid overwriting Platforms on Update All |
| Skip alternative ROMs | Ignore _alternatives folders when fetching assets (default on) |
| Compress and backup Saves and Memories | Backup during Update All |
| Show Menu Descriptions | Prompts/descriptions for Pocket Extras and similar |
| Use custom archive | Use the preconfigured “custom” archive entry instead of default archive.org |
| Automatically install updates to Pupdate | Self-update without prompt on startup |
| Use Local Pocket Extras | Use local pocket_extras.json |
| Use Local Display Modes | Use local display_modes.json |
| Cache downloaded archive files locally | Keep a reusable cache; optional cache path in JSON |
| Adds a description element to the video.json display modes | Non-breaking extra field in generated video JSON |
| Hide and uninstall Analogizer core variants | Hides Analogizer-specific core variants |
| Hide and uninstall AI-generated cores (Experimental) | Hides and (during Update All) uninstalls cores whose AI score exceeds your threshold. Toggle this on, then set the cutoff with Settings → Set AI Filter Threshold (see AI-generated core filter). Cores not included in the report are left alone. |
| Download files in concurrent chunks | Splits downloads into parallel HTTP range requests for faster transfers on bandwidth-limited servers like archive.org; falls back to a single connection when the server doesn't support ranges (default on). Tune the parallelism with config.download_chunk_count |
Game & Watch (and other core-specific archives) are enabled in the archives array in JSON, not via a separate Settings row.
Edit pupdate_settings.json for keys that are not bool menu toggles:
| Name | Description |
|---|---|
config.github_token | Used for GitHub API calls (rate limits); also settable under Pocket Setup → Set GitHub Token (classic) or Settings → Accounts → GitHub token (--tui) |
config.download_new_cores | yes / no / ask — set by Select Cores |
config.display_modes_option | merge / overwrite / ask; Pocket Setup → Manage Display Modes → Change Display Modes Option Setting (classic) or Settings → Display Modes → Merge or overwrite default (--tui) |
config.backup_saves_location | Backup output directory; Pocket Setup → Directory Locations → Set Backup Saves Location (classic) or Settings → Update All → Backup saves location (--tui) |
config.temp_directory | Override temp extract path (default: OS temp); Pocket Setup → Directory Locations → Set Temp Directory (classic) or Settings → Assets & Downloads → Temp directory (--tui) |
config.archive_cache_location | Override archive cache directory when caching is on; Pocket Setup → Directory Locations → Set Archive Cache Location (classic) or Settings → Assets & Downloads → Archive cache location (--tui) |
config.download_chunk_count | Number of parallel HTTP range chunks when Download files in concurrent chunks is on (default 4); ignored for files under 1 MB or servers without range support |
config.ai_core_threshold | Percentage 0–100 for the Hide and uninstall AI-generated cores filter; cores scoring over this value are hidden and uninstalled (defaults to 100, so no cores will ever be marked by default). Set via Settings → Set AI Filter Threshold (classic) or Settings → Core Filtering → AI score threshold (--tui) |
config.suppress_already_installed | Reduce “already installed” console noise |
config.use_local_cores_inventory | Use local cores.json and platforms.json (openFPGA Library v3 format) next to the executable |
config.use_local_blacklist | Use local blacklist.json instead of downloading |
config.use_local_image_packs | Use local image_packs.json |
config.use_local_ignore_instance_json | Use local ignore_instance.json |
archives | Archive definitions: internet_archive, custom_archive, core_specific_archive, core_specific_custom_archive (see below) |
credentials.internet_archive | Optional archive.org username/password |
core_settings.<core_id>.* | Per core: skip, download_assets, platform_rename, pocket_extras, pocket_extras_version, display_modes, original_display_modes, selected_display_modes, requires_license, pinned_version |
blacklist.json lists filenames not downloaded as assets. Entries support * and ? wildcards; matching applies to the full slot path and to the file name alone (useful for paths like subfolder/game.bin).
pupdate can mark or filter out cores that appear to be AI-generated, using the openFPGA AI check report built by neil-morrison44. Each core is given a score from 0 to 1. The closer to 1, the more likely it is to be AI generated.
How the score is calculated: An automated tool (openfpga-library/openfpga-ai-check) regularly looks through each core's public development history for signs that AI tools were used. For example, how often "co-authored by Claude" appears in commit messages. The more signs detected, the higher the score. A core that looks entirely AI made scores near 1, one that only had occasional AI help scores lower. Older cores from before AI tools were common are given a 0. Keep in mind this is an educated guess and it can be inaccurate. Core devs will be able to submit requests to fix incorrect detections. Use at your own risk (the risk really just being you will have some cores hidden from you with false positives)
--tui) - a percentage (0–100, defaults to 100). Cores that score over the threshold are labeled or hidden. Example: a threshold of 50 targets cores scoring above 0.50.100 to turn everything off (nothing scores above 1.0), including the labels.--tui), the Cores tab's details popup (Enter, or click [view]) shows the full report for that core: its score against your threshold, each individual check with the evidence it recorded (e.g. "Of the last 100 commit messages 97 mention Claude"), and when it was last analyzed. Cores missing from the report show as not scored.The archives array in pupdate_settings.json defines where assets come from. Stock config includes a default archive.org archive and a Retrodriven custom archive; you can switch via Use custom archive or edit JSON.
Types
internet_archive — name, archive_name (archive.org identifier).custom_archive — name, url, index (index format per archive.org JSON API).core_specific_archive — Same as internet_archive but scoped to one core name; optional file_extensions or files (not both); optional one_time.core_specific_custom_archive — Like core-specific but with url + index.Example core_specific_archive:
{
"name": "Spiritualized.2600",
"type": "core_specific_archive",
"archive_name": "htgdb-gamepacks",
"files": [
"@Atari 2600 2021-04-06.zip"
],
"enabled": true,
"one_time": true
}
Some items need login. Add to pupdate_settings.json:
"credentials": {
"internet_archive": {
"username": "me@something.com",
"password": "12345"
}
}
menu Interactive main menu (default)
-p, --path Absolute path to Pocket install / SD root
-s, --skip-update Open menu without checking for pupdate self-update
fund List sponsor / funding links
-p, --path
-c, --core Optional core id filter
update Run Update All (respects settings)
-p, --path
-c, --core Optional single core id
-r, --clean Clean reinstall cores
-u, --updated-assets-only Only check/download assets for cores updated this run
-y, --yes Non-interactive: assume defaults for all prompts (CI/cron)
uninstall Remove a core
-p, --path
-c, --core Required
-a, --assets Also remove Assets/{platform}/{core}
assets Download assets only
-p, --path
-c, --core Optional core id
firmware Check firmware
-p, --path
images Download a platform image pack
-p, --path
-o, --owner Repo owner
-i, --imagepack Repo name
-v, --variant Optional variant
instance-generator Run instance JSON generation (PC Engine CD workflow)
-p, --path
backup-saves Backup Saves & Memories
-p, --path
-l, --location Backup folder (required)
-s, --save Persist location in config for Update All
gameboy-palettes Download Game Boy palette pack
-p, --path
pocket-library-images Download Pocket library images
-p, --path
-n, --name Catalog entry id (omit for Spiritualized archive)
-i, --info Show details for -n
-l, --list List catalog ids (Spiritualized = no -n)
pocket-extras Install a Pocket Extra by id
-p, --path
-n, --name Extra id (required for install)
-i, --info Show details for name
-l, --list List all extras
display-modes Apply **recommended** display modes (same as curated menu action)
-p, --path
prune-memories Prune old save states (Memories)
-p, --path
-c, --core Optional core id
analogizer-setup Run Analogizer setup wizard
-p, --path
-j, --jotego Jotego-specific wizard
clear-archive-cache Clear cached archive downloads (same as Pocket Maintenance → Clear Archive Cache)
-p, --path
-y, --yes Required confirmation flag
validate-cores Check installed cores for missing or invalid JSON
-p, --path
-f, --fix Reinstall (clean) any cores with missing or invalid JSON
update-self Check for pupdate updates
help Help for a verb
version Print version
Non-interactive use (-y / --yes): a global flag. With it, pupdate assumes the default/affirmative answer to every prompt (install new cores, display modes, etc.) and skips the self-update prompt, so it can run unattended (CI, cron, containers). pupdate also returns a non-zero exit code when an update fails or an unhandled error occurs, so scripts can detect failures.
Examples
pupdate -p /path/to/sdcard/
pupdate update -c boogermann.bankpanic
pupdate update -p /path/to/sdcard/ --yes # unattended; non-zero exit on failure
pupdate assets -c jotego.jtcontra
pupdate images -i pocket-platform-images -o dyreschlock -v home
pupdate validate-cores
pupdate validate-cores --fix
Place jtbeta.zip from Patreon on the root of the SD card (exact name). Update All copies the beta key into the folders that need it. Do not rename the file.
jtbeta.zip (optional)Pupdate can download the latest jtbeta.zip for you. Manual placement (putting jtbeta.zip on the SD root yourself) always wins — auto-fetch only runs when no manual key is present. Two optional sources are supported; if both are enabled, GitHub is tried first and Patreon is the fallback.
Option A — GitHub (recommended):
Jotego distributes jtbeta.zip via a private GitHub repo (JTFPGA/jtbeta). Per Jotego's own Beta Files FAQ, access is granted to GitHub Sponsors of Jotego — and since Jotego's GitHub Sponsors page accepts Patreon as a payment route, existing Patreon patrons can get the same sponsor status (and therefore the repo invite) by linking their Patreon to their GitHub account.
JTFPGA/jtbeta once it arrives.repo scope, or a fine-grained PAT with Contents: Read on JTFPGA/jtbeta).github_token in pupdate_settings.json to that PAT.--tui).Option B — Patreon session cookie (experimental, fallback):
Experimental and flaky. This uses Patreon's undocumented frontend API with your browser session cookie, not a supported public API. Cookies expire (usually in weeks, sooner if you log out or clear cookies), and Patreon can change response field names without notice. Prefer Option A if you have any way to. Treat this as a best-effort fallback, not a stable integration.
pupdate will never use your Patreon session cookie for anything other than making HTTP requests to
patreon.comto locate and downloadjtbeta.zip(and, if you run the diagnostic, to verify your login and Jotego membership). It's stored locally inpupdate_settings.jsonand is never sent to any third party, telemetry endpoint, or server that isn'tpatreon.com.
https://www.patreon.com.session_id cookie.--tui), paste the value.--tui).Use Pocket Setup → Patreon Config → Test Patreon Session Cookie (Settings → Accounts → Test Patreon session cookie in --tui) to verify the cookie works and whether your account is currently a Jotego patron.
Notes:
jtbeta.zip on the SD root manually.Pocket Setup → Analogizer Config — choose Standard (RndMnkIII) or Jotego flow. For problems with generated files, ask the core author. Supported cores.
archives.Error in framework RS: bridge not responding — Run pupdate on a local disk, then copy results to the SD card.Missing ROM ID [1] in _alternatives — Turn off “Skip alternative ROMs” if you need those files installed.releases list.config.github_token in pupdate_settings.json.Failure processing application bundle / Default extraction directory ... is not accessible — Happens when running in a container (or any environment) where $HOME points to a directory that does not exist or is not writable. Either set DOTNET_BUNDLE_EXTRACT_BASE_DIR (or HOME) to a writable path, or download pupdate_linux_container*.zip from the release instead of pupdate_linux*.zip. The container variant places the native libs next to the binary so no runtime extraction is needed. Extract the whole archive and run pupdate from there.dotnet restore, dotnet build, dotnet run --project pupdate.csproj -- [verb] [options].src/Program.cs, src/partials/, src/services/, src/models/, src/options/, src/tui/ (the --tui interface).openfpga-cores-inventory / analogue-pocket
Thanks to neil-morrison44 — this project builds on his original script.
With special thanks to
Michael Hallett · RetroDriven · dyreschlock · espiox
30,138 followers · starred Aug 2022
17,025 followers · starred Feb 2023
1,573 followers · starred Nov 2022
259 followers · starred Mar 2025