# Igir turns a pile of ROMs into a named, deduplicated, tested collection

> A command line ROM collection manager written in TypeScript that sorts files by DAT, filters duplicates, writes archives, patches games and reports on what is missing. It never fetches anything itself, it only reshapes what you already have.

**emmercm/igir** — 🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.

- Repository: https://github.com/emmercm/igir
- Website: https://igir.io/
- Stars: 960 · Forks: 54
- Language: TypeScript
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/emmercm-igir

## A collection manager that only rearranges what you own

Igir is a zero-setup ROM collection manager for the command line, described as sorting, filtering, extracting or archiving, patching and reporting on collections of any size on any OS. The project is written in TypeScript, published to npm as igir, and documented at https://igir.io/.

The scope is deliberately narrow. Everything starts with DAT files, ROM files and ROM patches found on disk, including files sitting inside archives, and everything ends with files written to an output directory or a report you can read. There is no downloading, no scraping and no catalog service in the documentation. That boundary is the point: the tool takes a directory of files with inconsistent names and returns a directory of files that match a known naming scheme.

The audience is a collector or emulator user with a messy library, or a retro gaming hobbyist running hardware such as Analogue Pocket, Anbernic and MiSTER FPGA setups, or Batocera, Recalbox and RetroPie installations, all of which appear in the project's topic tags alongside the DAT families Logiqx, No-Intro, Redump and TOSEC. The related archive formats rvzstd and torrentzip, and the 1g1r one game per region idea, are likewise part of the vocabulary the tool speaks.

## Eleven commands, split between writing and checking

The command surface is small enough to hold in your head, and it divides cleanly. Five commands move data: copy moves ROM files from the input to the output directory, move does the same but relocates them, link creates links in the output directory back to the input files, extract pulls ROM files out of archives when copying or moving, and zip creates zip archives of ROMs when copying or moving.

Three commands produce references rather than content. The playlist command creates playlist files for multi-disc games, dir2dat generates a DAT from all input files, and fixdat generates a fixdat of any missing games for every DAT processed, which requires the dat option.

The last three are the checking half. The test command tests ROMs for accuracy after writing them, or tests input files if no write command is given, so it works as a standalone verifier. The clean command recycles unknown files in the output directory. The report command generates a CSV report on the known and unknown ROM files found in the input directories and also requires the dat option.

That report and fixdat pairing is the feature that makes the tool more than a renaming script. A fixdat is a manifest of what a DAT says should exist, which tells you the difference between a collection that is complete and one that quietly lost a disc.

## DAT files drive the naming, the filtering and the dedupe

The architecture is simple to describe: a DAT is the source of truth, and the input files are matched against it. When a DAT is supplied, Igir can organize ROM files by console, name them consistently including the right extension, and know which files are duplicates.

Filtering is where a collection actually gets smaller. The documented filtering options remove duplicate ROMs, and they can remove ROMs in languages you do not understand. The 1g1r tag in the project topics points at the same idea: one game per region rather than every regional variant on disk. Whether a file is a duplicate, a regional variant, or an unknown extra depends entirely on which DAT you feed in, which makes the choice of DAT the single most consequential decision in the whole workflow.

Headers are handled as a separate concept. Igir can parse ROMs with headers and optionally remove those headers, which matters for the formats where a header wrapper is part of the file format rather than corruption. The arcade side has its own path: Igir can build and re-build, in other words un-merge, split or merge, MAME ROM sets, and the MAME and fpga tags reflect that the tool understands set layouts rather than just loose files.

## Running Igir from the command line for a first pass

The documented install path is either a download for your OS from the releases page, or, if you have Node.js installed, npx so that the latest version always runs:

```shell
npx igir@latest [commands..] [options]
```

The bundled help message is the best reference for options, so it is worth reading in full from your own terminal:

```help
$ igir --help

Usage: igir [commands..] [options]
```

A sensible first run is a copy that touches nothing you still care about, followed by a test. The copy command duplicates ROM files from the input to the output directory, and the test command then verifies the written files for accuracy, or verifies the input files if you gave no write command at all. Running test on inputs before any write tells you whether the collection is clean to begin with, which separates your own bad dumps from anything Igir did.

The output directory is also where the unknown-file cleanup happens, and where a CSV report of known and unknown files lands. Start with copy into an empty directory so that clean has a well-defined scope.

## Building Igir from source with npm scripts and bun

Igir ships as an npm package with a bin entry pointing at dist/index.js, and the repository is a working TypeScript project rather than a released tarball only. The top level entries show the structure: src/ and packages/ hold the implementation, test/ holds the test suite, docs/ and mkdocs.yml drive the documentation site, scripts/ holds the build tooling, and there are separate bucket/ and addons/ directories.

The package scripts cover the whole lifecycle, and they are the commands to use if you want to run the project rather than the published version:

```json
"build": "tsx scripts/build.ts",
"compile": "bun scripts/compile.ts",
"lint": "eslint .",
"test": "npm run test:unit && npm run lint",
"test:unit": "tsc --noEmit && node ./node_modules/vitest/vitest.mjs"
```

The test script is worth noting for what it implies about the project. Type checking runs before the unit tests through tsc --noEmit, and linting runs after them, so a green test run means the type checker, the Vitest suite and ESLint all passed. There is a parallel bun path as well, with a test:unit:bun script and a bunfig.toml plus a .bun-version file in the tree, and separate scripts for holding, deprecating and auditing dependencies.

The practical consequence for an adopter is that Igir is a normal open source TypeScript project you can fork, patch and build yourself, with CI configuration under .github/ and coverage wired up through codecov.yml and vitest.config.ts.

## Patching in bulk, and the cases where Igir is the wrong tool

Patching is the capability that saves the most manual work, because applying ROM patches one at a time is exactly the repetitive task that drives people to look for a tool like this. Igir scans for ROM patches, including patches held inside archives, and applies them automatically. Combined with header parsing and removal, patching covers the two transformations that are most often done by hand: fixing a game that needs a translation or a bug fix patch, and stripping a header wrapper from a file that a different emulator expects to be raw.

There are clear limits. Igir is a file processing tool, so anything requiring knowledge of a game beyond its bytes, such as whether a patched build behaves correctly, is outside its reach. It also cannot tell you whether the DAT you selected is the right one, and a wrong DAT produces confident wrong results, wrong names and a fixdat full of games you never wanted. A collection where filenames are the only record of which revision you own, with no DAT available, is a case where the tool has little to add.

The documentation also lives in a separate site rather than in the repository README, so the option reference, the archive handling details and the filtering preference list have to be read at https://igir.io/. Expect to spend time there before a large run.

## GPL-3.0-or-later terms and a fast release cadence

The licence field on the repository says GPL-3.0, and package.json spells it out as GPL-3.0-or-later, authored by Christian Emmer. For a personal collection, that licence imposes nothing you have to think about. For anyone who wants to wrap Igir in a service, a kiosk interface or a commercial product, the copyleft terms are the deciding constraint, and the correct move is to read the LICENSE file and the official licence text rather than rely on the label.

The release history shows a project shipping quickly. Version 5.7.0 went out on 2026-10-01, 5.7.1 on 2026-10-07 and 5.7.2 on 2026-10-08, and the last push was on 2026-10-20, with the repository not archived. The package version in package.json matches the newest tag at 5.7.2.

That pace cuts both ways. A weekly or better release train means new DAT handling and new archive support can land without much ceremony, and it also means pinning a version matters if your workflow depends on exact output. Because the option set is broad and the default behaviour of commands such as clean changes the contents of your output directory, treat an upgrade as a change to a tool that can delete files, and pin the version you have validated.

## Conclusion

Igir suits someone who already owns a folder of ROMs and wants it to become a correctly named, verified, deduplicated set without doing it by hand, and it suits anyone who needs a fixdat listing of what a DAT expects but the collection lacks. It does not suit someone hunting for the games themselves, since the documentation describes only reading and rewriting files you point it at, and it does not suit a commercial product that cannot accept GPL-3.0-or-later terms. Verify first that your DAT source matches the console you are sorting, then run igir test against the result, because that command is what tells you whether the rewritten collection still hashes correctly.

## FAQ

### How do I install and run Igir?

Download the build for your OS from the GitHub releases page, or, with Node.js installed, run npx igir@latest [commands..] [options] to always use the latest published version. Full documentation and usage examples are at https://igir.io/.

### Can Igir find and download the ROMs that are missing from my collection?

The documented commands read, rewrite and report on files in the input directories you point them at, and the report and fixdat commands tell you what a DAT expects versus what you hold. No download or catalog feature is described.

### What is a fixdat in Igir and when should I generate one?

The fixdat command generates a fixdat of any missing games for every DAT processed, and it requires the dat option. It is the way to see the gap between a DAT definition and your collection.

### How does Igir handle duplicate and multi-region ROMs?

When a DAT is supplied, Igir can filter out duplicate ROMs and can filter out ROMs in languages you do not understand, and it can create playlist files for multi-disc games with the playlist command. The result depends on which DAT you supply.

## Sources

- [emmercm/igir on GitHub](https://github.com/emmercm/igir)
- [License: GPL-3.0](https://github.com/emmercm/igir/blob/main/LICENSE)
- [Project website](https://igir.io/)
- [README](https://github.com/emmercm/igir/blob/main/README.md)
- [Releases](https://github.com/emmercm/igir/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/emmercm-igir
