oxyROMon is a cross-platform, opinionated ROM organizer written in Rust. It checks ROM files against known-good Logiqx DAT files, imports them into a tidy directory tree, and sorts them by region, in one-game-one-ROM (1G1R) mode, or both.
It is designed with archiving in mind, so it only keeps original and lossless formats. It can still export to popular lossy formats, leaving your lossless files untouched. Console and computer systems use No-Intro or Redump DATs, and arcade systems (work in progress) use MAME or FBNeo DATs.
Every format is handled in-process, so oxyROMon needs no external tool.
oxyROMon comes in three flavors, all driving the same code and the same database:
- A command-line tool, the core of the project.
- A web UI, served by
oxyromon server, also available as a desktop app. - A Model Context Protocol (MCP) server, so an AI assistant can explore and maintain your library.
A system is created from a Logiqx DAT file:
- Cartridge-based consoles and older computers: Dat-o-Matic (No-Intro).
- Disc-based consoles: Redump, or let
download-datsfetch them for you. - MAME: Progetto-Snaps.
- FBNeo: harder to find, libretro has some.
Then the usual loop is:
oxyromon config -s ROM_DIRECTORY /path/to/Emulation # where your library lives
oxyromon config -s REGIONS_ALL US,EU,JP # regions to keep
oxyromon config -s REGIONS_ONE US,EU # 1G1R regions, by preference
oxyromon import-dats "Nintendo - Game Boy (20260101-000000).dat"
oxyromon import-roms ~/Downloads/roms
oxyromon sort-roms --system "Game Boy"ROM files that match the database are moved into their system's directory, the rest are left alone.
sort-roms then distributes them according to your settings, and needs at least one region in REGIONS_ALL or REGIONS_ONE.
From there, convert-roms switches formats, check-roms verifies integrity, and purge-roms empties the Trash directories and forgets files you deleted by hand.
- Binaries for Linux, macOS and Windows are on the release page, along with the desktop app and the format crates' command-line tools.
- Arch Linux has a package in the official repositories.
- Docker images are on Docker Hub, Alpine-based, with
/dataholding the database and/romsthe library. - crates.io:
cargo install oxyromonbuilds the command-line tool.
The command-line tool has no special requirement beyond a C toolchain, which the RVZ backend needs:
cargo build --releaseThe web UI is a Leptos app compiled to WebAssembly and embedded into the binary. It needs the Trunk bundler and the WebAssembly target:
rustup target add wasm32-unknown-unknown
cargo install --locked trunk
cargo build --release --features serverSet SKIP_TRUNK=true to reuse web assets you already built.
The desktop app lives in desktop/.
It wraps the web UI in a Tauri window and starts a bundled oxyromon server behind it, so it shares the command-line tool's database and settings.
It needs everything the web UI needs, the Tauri CLI, and your platform's webview development packages.
On Linux, those are webkit2gtk-4.1, gtk3, librsvg and libayatana-appindicator.
cargo install --locked tauri-cli --version "^2"
cd desktop
cargo tauri build # or `cargo tauri dev` while working on itThe repository also holds oxyROMon's format crates, under crates/.
Each is a library and a standalone command-line tool:
cargo build --release -p chd-rs -p gdi-rs -p nsz-rs -p wux-rs -p xdelta-rs -p xps-rs -p xso-rs| Feature | Description | Default |
|---|---|---|
mcp |
The MCP server over stdio | |
server |
The web server and UI, which also serves MCP over HTTP | |
use-rustls |
TLS through rustls | ✔ |
use-native-tls |
TLS through the system's OpenSSL |
To use OpenSSL instead of rustls:
cargo build --release --no-default-features --features use-native-tlsSettings are stored in the database and managed with the config subcommand.
They are global by default.
Pass -n/--system to override one for a single system, which then falls back to the global value when unset.
The database lives in the platform's data directory, under oxyromon.
These environment variables change where things go:
| Variable | Purpose |
|---|---|
OXYROMON_DATA_DIRECTORY |
The directory holding the database |
OXYROMON_ROM_DIRECTORY |
The initial ROM_DIRECTORY, used only until it is set |
OXYROMON_TMP_DIRECTORY |
The initial TMP_DIRECTORY, used only until it is set |
OXYROMON_LOG_LEVEL |
Log verbosity, in env_logger syntax |
| Setting | Description | Default |
|---|---|---|
ROM_DIRECTORY |
Your ROM library | ~/Emulation |
TMP_DIRECTORY |
Scratch space for conversions, at least 8 GB for DVDs | The system's temp directory |
| Setting | Description | Default |
|---|---|---|
REGIONS_ALL |
Regions for which to keep every game, unordered (eg: US,EU,JP) |
|
REGIONS_ONE |
Regions for 1G1R, by order of preference (eg: US,EU) |
|
REGIONS_ALL_SUBFOLDERS |
Subfolders for games: none or alpha |
none |
REGIONS_ONE_SUBFOLDERS |
Subfolders for 1G1R games: none or alpha |
none |
REGIONS_ONE_STRICT |
Elect 1G1R games whether you own them or not | false |
REGIONS_ALL_ARCADE |
Arcade set types for the main directory: bios, parent, clone |
|
REGIONS_ONE_ARCADE |
Arcade set types for the 1G1R directory: bios, parent, clone |
|
PREFER_PARENTS |
Favor parents in the 1G1R election | true |
PREFER_REGIONS |
Favor games released in more (broad) or fewer (narrow) regions, or neither (none) |
none |
PREFER_VERSIONS |
Favor new or old revisions, or neither (none) |
new |
PREFER_FLAGS |
Flags to favor in the 1G1R election (eg: Rumble Version) |
|
DISCARD_FLAGS |
Flags to discard (eg: Virtual Console) |
|
DISCARD_RELEASES |
Releases to discard (eg: Beta,Proto) |
|
LANGUAGES |
Languages to keep, for games that list theirs (eg: En,Ja) |
|
GROUP_SUBSYSTEMS |
Put every variant of a system in the same directory | true |
GAME_SUBFOLDERS |
Put games in folders named after them: never, multiple (those stored as several files) or always |
never |
| Setting | Description | Default |
|---|---|---|
PREFER_FORMAT |
Format imported ROMs are converted to: ORIGINAL, 7Z, CHD, CSO, NSZ, RVZ, ZIP, ZSO; arcade systems take only ORIGINAL and ZIP |
|
CHD_PARENTS |
Use the other discs of a game as CHD parents, which needs playlists to have been generated | false |
CHD_CD_HUNK_SIZE |
CHD hunk size in bytes for CDs, 16 to 1048576 |
auto |
CHD_CD_COMPRESSION_ALGORITHMS |
Up to 4 CHD codecs for CDs: none, cdfl, cdlz, cdzl, cdzs |
auto |
CHD_DVD_HUNK_SIZE |
CHD hunk size in bytes for DVDs, 16 to 1048576 |
auto |
CHD_DVD_COMPRESSION_ALGORITHMS |
Up to 4 CHD codecs for DVDs: none, flac, huff, lzma, zlib, zstd |
auto |
CHD_HD_HUNK_SIZE |
CHD hunk size in bytes for hard disks, 16 to 1048576 |
auto |
CHD_HD_COMPRESSION_ALGORITHMS |
Up to 4 CHD codecs for hard disks: none, flac, huff, lzma, zlib, zstd |
auto |
CHD_LD_HUNK_SIZE |
CHD hunk size in bytes for LaserDiscs, 16 to 1048576 |
auto |
CHD_LD_COMPRESSION_ALGORITHMS |
CHD codecs for LaserDiscs: none, avhu |
auto |
RVZ_BLOCK_SIZE |
RVZ block size in KiB, 32 to 2048 |
128 |
RVZ_COMPRESSION_ALGORITHM |
RVZ codec: none, zstd, bzip2, lzma, lzma2 |
zstd |
RVZ_COMPRESSION_LEVEL |
RVZ level, 1 to 22 for zstd and 1 to 9 otherwise |
5 |
SEVENZIP_COMPRESSION_ALGORITHM |
7Z codec: lzma2 or zstd |
lzma2 |
SEVENZIP_COMPRESSION_LEVEL |
7Z LZMA2 level, 1 to 9 |
9 |
SEVENZIP_ZSTD_COMPRESSION_LEVEL |
7Z Zstandard level, 1 to 22 |
19 |
SEVENZIP_SOLID_COMPRESSION |
Solid 7Z archives | false |
ZIP_COMPRESSION_ALGORITHM |
ZIP codec: deflate or zstd |
deflate |
ZIP_COMPRESSION_LEVEL |
ZIP Deflate level, 1 to 9 |
9 |
ZIP_ZSTD_COMPRESSION_LEVEL |
ZIP Zstandard level, 1 to 22 |
19 |
Zstandard archives are opt-in.
They compress much faster than LZMA2 at a comparable size, but almost nothing else reads them.
7-Zip, emulators and Windows Explorer cannot open a Zstandard .7z or .zip, so keep them for archival rather than for a library you play from.
${ROM_DIRECTORY}
├── ${SYSTEM_NAME} # each system's games, from the regions you keep
│ ├── 1G1R # its 1G1R games
│ └── Trash # its discarded games
└── Trash # files import-roms -t matched to no system
GROUP_SUBSYSTEMS controls ${SYSTEM_NAME}: when on, every variant of a system shares one directory.
GAME_SUBFOLDERS puts games in folders named after them within their system's directory, so a game of several files stays together.
With always, every game gets one; with multiple, only a game stored as several files does, a CUE and its BINs, while one in a single archive or disc image stays as it is.
Under either, the discs of a game share one folder with their playlist, named after the game without its (Disc N) tag, as frontends such as RomM read a multi-disc game.
Arcade games stored as archives stay as they are.
| Format | Import and check | Convert | Export | Backend |
|---|---|---|---|---|
| Original files | ✔ | ✔ | ✔ | |
| 7Z, ZIP | ✔ | ✔ | ✔ | sevenz-rust2, zip |
| CHD | ✔ | ✔ | ✔ | chd-rs |
| CSO, ZSO | ✔ | ✔ | ✔ | xso-rs |
| NSZ | ✔ | ✔ | ✔ | nsz-rs |
| RVZ | ✔ | ✔ | ✔ | nod |
| WBFS | ✔ | nod | ||
| WUX (Wii U) | ✔ | ✔ | ✔ | wux-rs |
| WUA (Wii U) | ✔ | ✔ | ✔ | wux-rs |
| NUS folder (Wii U) | ✔ | wux-rs | ||
| GDI | ✔ | gdi-rs | ||
| ISO (from CUE/BIN) | ✔ | |||
| CIA | ✔ | cia-rs | ||
| JB folders (PS3) | ✔ | IRD files | ||
| BPS, IPS, XDELTA patches | ✔ | xps-rs, xdelta-rs |
The crates without a link are oxyROMon's own, in crates/.
Each began as a port of the tool oxyROMon used to run: chdman, ctrtool, maxcso, nsz, gdidrop, Flips and xdelta3.
wux-rs instead follows wudd and Cemu, as oxyROMon never ran a tool for the Wii U.
Your Switch keys, at ~/.switch/prod.keys, are only needed to compress NSPs that contain NCAs.
Importing, checking and decompressing NSZs never need them.
RVZ files are interchangeable with Dolphin's in both directions.
Wii U discs are WUDs, which Redump lists as ISOs, so that is what converting back to the original gives; a .wud found in the wild is matched and renamed all the same.
WUX compresses a WUD losslessly, as wudd dumps it and Cemu reads it.
WUA is Cemu's archive of a disc's decrypted game files, and a WUA oxyROMon writes is lossless too: it also keeps, where Cemu doesn't look, what rebuilds the disc byte for byte, its partitions' layout and headers and the data a WUA otherwise drops, so it converts back to WUX or to the original ISO, checked against the disc's SHA-1.
Every Wii U disc carries a system update, about 1.3 GB, which the many discs carrying the same one share: a WUA keeps it in a hidden .update-partitions folder in its system's directory, once for every WUA there, decrypted and compressed to about 600 MB, as NKit keeps its recovery partitions.
Mario Tennis: Ultra Smash, a 2.1 GB WUX, becomes an 0.8 GB WUA, with 0.6 GB of update partition shared with the other discs carrying its update.
purge-roms -f deletes the update partitions no WUA needs any more, keeping them all if a WUA can't be read, and importing a WUA brings the ones it needs from the .update-partitions folder next to it.
WUAs Cemu writes, or oxyROMon did before, can't rebuild their disc and are not lossless.
A WUA oxyROMon writes also keeps revert data for each title it holds: wuxrs turns it back into a NUS folder per title, whose contents are byte for byte the disc's and its update's, checked against their TMDs.
WUA and NUS need the disc's key and the Wii U common key, neither of which ships with oxyROMon.
import-keys stores them in oxyROMon's data directory, so a headless server needs no emulator.
It reads files in the format of Cemu's keys.txt, one key per line, where the common key can sit alongside the disc keys, and a console's OTP dump, otp.bin, for the Wii U and vWii common keys.
Wii U updates and DLC are games of their own, as No-Intro's CDN DAT lists them: a folder per title, holding its TMD, ticket and content files as Nintendo's servers deliver them.
Each title keeps its files in a folder of its own, since every title names them alike.
Converted to 7Z or ZIP, a title's folder becomes one archive in its place, and its files go back in their folder when converted or exported to ORIGINAL.
No-Intro lists each title once, with every version's TMD and every content any version used, while Nintendo's servers deliver only the newest version: a title counts as complete with its newest TMD and the files that TMD lists, the older ones being ignored.
No-Intro sometimes leaves a hashed content's H3 file out of its DAT, though a title installs only with every one: importing leaves such a file where it is, and exporting the title rebuilds it from its content and checks it against the TMD, which needs the Wii U common key.
Exporting a disc to WUA adds the newest update and DLC in the library, from any system, matched by title ID, as Cemu bundles them.
A title needs its ticket to be decrypted: No-Intro lists every update with one, but no DLC, which Nintendo's servers deliver without one.
Importing a title's folder keeps the ticket a downloader made, when no DAT lists it, in a wiiu_tickets folder in oxyROMon's data directory, beside the keys, by title ID; importing the folder of a title already imported keeps it too.
Exporting to WUA decrypts the title with it, and exporting the title for a console adds it as title.tik, which WUP Installer GX2 needs; DLC without a ticket is skipped with a warning.
Exporting a disc to NUS writes the folder WUP Installer GX2 installs on a console: the disc's TMD, ticket and certificates, and the game's contents, each checked against the TMD.
A folder already in its place is only replaced if it holds nothing the export wouldn't write, as an earlier export of the same disc; otherwise the export fails and leaves it alone.
A disc's game partition holds the title's CDN contents byte for byte, so every .app and .h3 matches No-Intro's CDN DAT; only title.tmd differs, as Nintendo signed one for the disc and another for its servers.
oxyromon server serves the web UI at http://127.0.0.1:8000 by default, and the desktop app shows the same UI in its own window.
From there you can browse systems, games and ROM files, see each system's completion, download a ROM file, edit global and per-system settings, purge a system, import DAT files, uploaded or fetched from Redump, and import ROM files.
The server has no authentication. It can also import ROM files from a URL, which the server itself downloads, so it reaches anything the server can reach. Keep it on the default loopback address unless you trust your network.
The MCP server lets an AI assistant explore and maintain your library with the same actions as the command-line tool:
- Read-only tools:
status,list_systems,get_system,list_games,get_game,search_games,get_settings,downloadable_systemsandparse_game_name. - Mutating tools:
import_dats,download_dats,import_roms,sort_roms,check_roms,convert_romsandset_setting. - Destructive tools:
purge_roms,purge_systems,purge_gamesandpurge_irds, which refuse to run withoutconfirm: true.
Mutating tools run to completion within the call, report progress as they go, and can be cancelled.
The server also exposes resources (oxyromon://status, oxyromon://systems, oxyromon://systems/{id} and oxyromon://settings) and two guided prompts, onboard_system and audit_system.
oxyromon mcp speaks over stdio, and --read-only hides every mutating tool:
{
"mcpServers": {
"oxyromon": {
"command": "oxyromon",
"args": ["mcp"]
}
}
}oxyromon server also serves it over HTTP at /mcp:
{
"mcpServers": {
"oxyromon": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}Usage: oxyromon [COMMAND]
Commands:
info Print system information
config Query and modify the oxyromon settings
create-dats Create DAT files from directories
import-dats Parse and import Logiqx DAT files into oxyromon
download-dats Download No-Intro and Redump DAT files and import them into oxyromon
import-irds Parse and import PlayStation 3 IRD files into oxyromon
import-patches Import patch files into oxyromon
import-keys Import Wii U keys into oxyromon
import-roms Validate and import ROM files or directories into oxyromon
purge-games Move the files of games to the trash
purge-irds Unassociate games from IRD files
sort-roms Sort ROM files according to region and version preferences
convert-roms Convert ROM files between common formats
export-roms Export ROM files to common formats
rebuild-roms Rebuild arcade ROM sets according to the selected strategy
check-roms Check ROM files' integrity
purge-roms Purge trashed, missing, and orphan ROM files
purge-systems Purge systems
generate-playlists Generate M3U playlists for multi-disc games
benchmark Benchmark oxyromon
mcp Serve the Model Context Protocol on stdin/stdout
server Launch the backend server
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
mcp needs the mcp feature, and server the server feature.
Prints the version, every format backend and its version, and some library statistics.
Usage: oxyromon info
Options:
-h, --help Print help
Lists, reads, sets and unsets settings, and adds or removes entries of list settings.
Every operation is global unless -n/--system scopes it to one system.
Usage: oxyromon config [OPTIONS]
Options:
-n, --system <NAME> Select a system by name (supports % globs)
-l, --list Print the whole configuration
-g, --get <KEY> Print a single setting
-s, --set <KEY> <VALUE> Set a single setting
-u, --unset <KEY> Unset a single setting
-a, --add <KEY> <VALUE> Add an entry to a list
-r, --remove <KEY> <VALUE> Remove an entry from a list
-h, --help Print help
Builds a DAT file from a directory, which oxyROMon or any other tool can then import. Name and description default to the directory's name, and the version to the current date and time, No-Intro style. Each file becomes a game named after the file without its extension, with all three checksums, computed in one read.
Files are hashed as they are and subdirectories are ignored, with two exceptions. A WUX is listed as the WUD it holds, decompressed as it is hashed, so the DAT matches the disc in either format. A Wii U title's folder, found by its TMD, becomes one game whose ROMs are its files, as No-Intro lists updates and DLC. Otherwise, use original, uncompressed files if you plan to import the DAT and then convert or export its ROMs.
Usage: oxyromon create-dats [OPTIONS] <DIRECTORIES>...
Arguments:
<DIRECTORIES>... Set the directories to process
Options:
-n, --name <NAME> Customize the DAT name
-d, --description <DESCRIPTION> Customize the DAT description
-v, --version <VERSION> Customize the DAT version
-a, --author <AUTHOR> Customize the DAT author
-u, --url <URL> Customize the DAT URL
-o, --output <OUTPUT> Customize the output directory
-h, --help Print help
Imports Logiqx DAT files from No-Intro, Redump or MAME, including Parent-Clone DATs.
ZIP files such as No-Intro's daily packs are read directly, including DATs in nested directories.
The output of MAME's or HBMAME's -listxml is read directly too: having no header, its system is named after the file, which -n overrides, and versioned after the build.
With -u, only systems already in the database are updated, which keeps a collection in sync with those packs.
An update keeps a system's custom name and extension unless new ones are given.
-f sets each to what is given, so one left out reverts to the DAT's.
When an update moves ROM files, to a renamed game or to Trash, the directories they leave empty are deleted, except the ROM, system and Trash directories.
Some systems need a header definition next to their DAT file. oxyROMon falls back to its own when it is missing.
A DAT that lists machines, like MAME's, is imported as an arcade system.
FBNeo's arcade DATs list games, so import them with -a to make them arcade.
An update keeps a system arcade, and -f without -a reverts it.
MAME ships separate DATs for ROMs, CHDs and more.
Turn GROUP_SUBSYSTEMS on and name them MAME (ROMs), MAME (CHDs) and so on, so they share a MAME directory that MAME reads as is.
Usage: oxyromon import-dats [OPTIONS] <DATS>...
Arguments:
<DATS>... Set the DAT files to import
Options:
-i, --info Show the DAT information and exit
-u, --update Only import DAT files for systems already in the database
-s, --skip-header Skip parsing the header even if the system has one
-f, --force Force import of outdated DAT files
-n, --name <NAME> Customize the system name
-e, --extension <EXTENSION> Customize the system extension
-a, --arcade Import as arcade systems, for DATs that list games instead of machines
-h, --help Print help
Redump offers direct downloads, so this can download and import new Redump systems and update those you have.
A DAT no newer than the imported one changes nothing, unless -f forces it.
A system that fails to download is reported and skipped, and the run then fails, naming it.
No-Intro offers no direct downloads, so for No-Intro it only reports which systems have an update.
As with import-dats, an update keeps custom names and extensions, and -f reverts them.
Usage: oxyromon download-dats [OPTIONS]
Options:
-n, --nointro Download No-Intro DAT files
-r, --redump Download Redump DAT files
-u, --update Check for system updates
-a, --all Import all systems
-f, --force Force import of outdated DAT files
-s, --save <DIRECTORY> Save downloaded DAT files to the specified directory
-h, --help Print help
Imports PlayStation 3 IRD files, which validate JB folders, the extracted form PS3 games are usually dumped in.
A game counts as complete without its PS3_CONTENT, PS3_EXTRA and PS3_UPDATE directories.
When an IRD no longer matches a file already in its JB folder, that file is imported again or moved to Trash.
Import a PS3 DAT first.
If it doesn't come from Redump, make sure its name contains PlayStation 3.
Only IRD version 9, the latest, is supported.
Usage: oxyromon import-irds [OPTIONS] <IRDS>...
Arguments:
<IRDS>... Set the IRD files to import
Options:
-i, --info Show the IRD information and exit
-f, --force Force import of already imported IRD files
--system <SYSTEM> Select the system to import into, matching the game and ROM automatically
-h, --help Print help
Removes the ROMs an IRD import created, moving their files to the system's Trash directory.
The game is no longer a JB folder afterwards, so a different IRD can be imported.
Usage: oxyromon purge-irds [OPTIONS] [GAMES]...
Arguments:
[GAMES]... Set the game names to purge
Options:
--system <SYSTEM> Select the system to purge from, skipping the prompt and purging every IRD game when no names are given
-h, --help Print help
Imports BPS, IPS and XDELTA patches, named after their ROM files following RetroArch's softpatching convention.
Usage: oxyromon import-patches [OPTIONS] <PATCHES>...
Arguments:
<PATCHES>... Set the patch files to import
Options:
-n, --name Customize patch names
-f, --force Force import of already imported patch files
--rom <ROM> Select the target ROM by id, skipping the prompts
-h, --help Print help
Imports Wii U keys, which exporting to WUA needs, from files in the format of Cemu's keys.txt: one 32-digit hex key per line, with anything after # or ; ignored.
Disc keys and the Wii U common key can share a file.
A console's OTP dump, otp.bin, can be imported too: its Wii U and vWii common keys are taken from it, the vWii key serving the vWii titles a disc's update partition can carry.
The keys are merged into wiiu_keys.txt in oxyROMon's data directory, readable by its owner only, each key kept once, so importing again after new dumps only adds the new ones.
Usage: oxyromon import-keys <KEYS>...
Arguments:
<KEYS>... Set the key files to import, as Cemu's keys.txt or a Wii U's otp.bin
Options:
-h, --help Print help
Hashes files and directories and moves those that match the database into their system's directory.
The system is usually detected, but you can narrow the search with -s, by a case-insensitive partial name.
-s is also needed to match headered ROMs, for the Nintendo Entertainment System (Headerless), Famicom Disk System, Atari 7800 and Atari Lynx.
Files are moved as they are, except archives holding several games, which are extracted.
When the system has a PREFER_FORMAT, imported ROMs are then converted to it, unless you pass --as-is.
Files needing a choice, such as JB folders or ambiguous matches, prompt by default, and -u skips them or picks the first match instead.
Consoles accept every No-Intro and Redump format, 7Z, ZIP, CHD, CIA, CSO, NSZ, RVZ, WUA, WUX, ZSO, JB folders and Wii U title folders.
A Wii U title folder, an update or DLC as Nintendo's servers deliver it, is found by its TMD, and either a downloader's names (title.tmd, 00000000.app) or No-Intro's (tmd.32, 00000000) will do.
Arcade systems accept uncompressed files, ZIP and CHD.
Usage: oxyromon import-roms [OPTIONS] <ROMS>...
Arguments:
<ROMS>... Set the ROM files or directories to import
Options:
-s, --system <SYSTEM> Select systems by name
-t, --trash Trash invalid ROM files
-d, --delete Delete invalid ROM files (hard delete)
-f, --force Force import of existing ROM files
-u, --unattended <MODE> Handle ROM files that require human intervention (skip: skip, first: auto-select first match) [default: none] [possible values: none, skip, first]
-x, --extract Extract top-level archives before importing their contents
-a, --as-is Import ROM files as-is without converting them
-h, --help Print help
Moves games between the system directory, 1G1R and Trash, according to your settings.
- Regions mode keeps every game from the
REGIONS_ALLregions in the system directory. - 1G1R mode keeps one game per Parent-Clone group in
1G1R, elected byREGIONS_ONEorder and thePREFER_*settings. - Hybrid mode does both: the 1G1R election, plus every remaining game from the
REGIONS_ALLregions.
By default, the election only considers games you own.
REGIONS_ONE_STRICT makes it follow your preferences regardless, so a missing game shows as wanted instead of being replaced.
1G1R is useful even without a Parent-Clone DAT: it separates the games you play from, say, Japanese originals kept for translation patches.
Arcade systems sort by set type instead.
REGIONS_ALL_ARCADE and REGIONS_ONE_ARCADE say which of bios, parent and clone go to each directory.
With both empty, everything stays in the system directory, and otherwise the types left out are discarded.
Discarded games always go to Trash.
Regions use TOSEC's two-letter codes, and ZZ, the unknown region, works as a catch-all in REGIONS_ALL.
Usage: oxyromon sort-roms [OPTIONS]
Options:
-r, --regions <REGIONS_ALL>...
Set the regions to keep (unordered)
--subfolders <REGIONS_ALL_SUBFOLDERS>
Set the subfolders scheme for games [possible values: none, alpha]
-o, --1g1r <REGIONS_ONE>...
Set the 1G1R regions to keep (ordered)
--1g1r-subfolders <REGIONS_ONE_SUBFOLDERS>
Set the subfolders scheme for 1G1R games [possible values: none, alpha]
-w, --wanted
Show wanted games
-a, --all
Sort all systems
-s, --system <SYSTEM>
Select systems by name
-y, --yes
Automatically say yes to prompts
-h, --help
Print help
Converts ROM files between lossless formats and back to their originals:
- Any original format to and from 7Z and ZIP.
- CUE/BIN and ISO to and from CHD, with CHDs restored to their original split CUE/BIN.
- ISO to and from CSO, ZSO and RVZ.
- NSP to and from NSZ.
- Wii U discs between ISO, WUX and lossless WUA.
Games and systems are selected by case-insensitive name, with SQL wildcards, and both flags can be repeated.
--save also stores the format as each processed system's PREFER_FORMAT, so future imports follow it.
Usage: oxyromon convert-roms [OPTIONS]
Options:
-f, --format <FORMAT> Set the destination format [possible values: ORIGINAL, 7Z, CHD, CSO, NSZ, RVZ, WUA, WUX, ZIP, ZSO]
-g, --game <GAME> Select games by name
-s, --system <SYSTEM> Select systems by name
-a, --all Convert all systems/games
-r, --recompress Force conversion even if already in the selected format
-d, --diff Print size differences
-c, --check Check ROM files after conversion
-p, --parents Prompt for CHD parents
-S, --save Persist the format as the systems' preferred format (PREFER_FORMAT)
-h, --help Print help
Like convert-roms, but writes copies to another directory and leaves your library untouched, so lossy formats are allowed.
It is meant for real hardware, through an EverDrive or an optical drive emulator.
ISO targets OPL on the PlayStation 2.
It turns CUE/BIN CD games into an ISO of the first track's 2048-byte data sectors, as bchunk does, keeping only that track for multi-track games.
Usage: oxyromon export-roms [OPTIONS] --directory <DIRECTORY>
Options:
-f, --format <FORMAT> Set the destination format [possible values: ORIGINAL, 7Z, CHD, CSO, GDI, ISO, NSZ, NUS, RVZ, WBFS, WUA, WUX, ZIP, ZSO]
-g, --game <GAME> Select games by name
-s, --system <SYSTEM> Select systems by name
-d, --directory <DIRECTORY> Set the output directory
-o, --1g1r Export 1G1R games only
-h, --help Print help
Rebuilds arcade sets with another merging strategy:
- Split: each set holds only its own files.
- Non-merged: each set also holds its parent's files.
- Full non-merged: each set also holds its parent's files and the BIOS files it needs.
- Merged: a parent's ZIP also holds its clones' files, each stored once. A clone's file whose name the parent already uses with other contents goes under
<clone>/, as ClrMamePro does. Sets must be ZIPs: convert loose sets withconvert-romsfirst.
Usage: oxyromon rebuild-roms [OPTIONS]
Options:
-m, --merging <MERGING> Set the arcade merging strategy [possible values: SPLIT, NON_MERGED, FULL_NON_MERGED, MERGED]
-f, --force Force rebuild even if merging strategy is unchanged
-a, --all Rebuild all arcade systems
-y, --yes Automatically say yes to prompts
-h, --help Print help
Hashes every ROM file of the selected systems again and moves corrupt ones to Trash.
--size also recomputes stored file sizes.
Usage: oxyromon check-roms [OPTIONS]
Options:
-a, --all Check all systems
-g, --game <GAME> Select games by name
-s, --size Recalculate ROM file sizes
--system <SYSTEM> Select systems by name
-h, --help Print help
Forgets ROM files that went missing or that no ROM references, and deletes the files in every Trash directory, the ROM directory's own included.
--foreign deletes files in the ROM directory that the database doesn't know.
Directories left empty are deleted, except the ROM, system and Trash directories.
Usage: oxyromon purge-roms [OPTIONS]
Options:
-m, --missing Delete missing ROM files from the database
-o, --orphan Delete ROM files without an associated ROM from the database
-t, --trash Physically delete ROM files from the trash directories
-f, --foreign Physically delete ROM files unknown to the database
-y, --yes Automatically say yes to prompts
-h, --help Print help
Moves the files of games to their system's Trash, for you to delete afterwards with purge-roms --trash.
The games stay in the database, now missing, and sort-roms leaves their files where they are.
A file that also holds ROMs of a game not being purged, such as a merged arcade set, stays in place, and so does a multi-disc playlist until all its discs are purged.
Without --game, it prompts for games among those with files.
Usage: oxyromon purge-games [OPTIONS]
Options:
-s, --system <SYSTEM> Select systems by name
-g, --game <GAME> Select games by exact name
-h, --help Print help
Removes systems and their ROMs from the database and moves their files to Trash, for you to delete afterwards.
Usage: oxyromon purge-systems [OPTIONS]
Options:
-e, --empty Only list empty systems for selection
-s, --system <SYSTEM> Select systems by name
-h, --help Print help
Writes M3U playlists for multi-disc Redump games, so RetroArch can swap discs.
The playlists also tell CHD_PARENTS which discs belong together.
sort-roms moves playlists along with their games, but run this again after convert-roms.
Usage: oxyromon generate-playlists [OPTIONS]
Options:
-a, --all Generate playlists for all systems
-h, --help Print help
Measures read and write speeds in the ROM and temporary directories, and ranks the checksum algorithms. CRC is usually fastest, then SHA1, then MD5, though it depends on your hardware.
Usage: oxyromon benchmark [OPTIONS]
Options:
-c, --chunk-size <CHUNK_SIZE> Set the chunk size in KB for read and writes (Default: 256) [default: 256]
-h, --help Print help
Serves MCP over stdio, as described in MCP server. Nothing else may write to standard output while it runs.
Usage: oxyromon mcp [OPTIONS]
Options:
--read-only Expose only non-mutating tools
-h, --help Print help
Serves the web UI at /, the GraphQL API at /graphql, and MCP at /mcp.
Usage: oxyromon server [OPTIONS]
Options:
-a, --address <ADDRESS> Specify the server address [default: 127.0.0.1]
-p, --port <PORT> Specify the server port [default: 8000]
-h, --help Print help
- Add more actions to the web UI
- Find a way to automatically download No-Intro DAT files
- Support merged sets for arcade systems
- Write tests for arcade systems, for NSZ with a compressible NCA, and for IRD and PS3 in general
- Support rebuilding PS3 ISOs from IRD files, if possible and requested
- Add a metadata scraper in the RetroArch format
AGENTS.md holds the project's conventions, and openwiki/ a generated wiki of how the code works.

