Stable-Retro: Gymnasium Environments for Over 1000 Emulated Games
A fork of gym-retro with additional games, emulators and supported platforms
At a glance
- What is it?
- Stable-Retro is a fork of OpenAI's gym-retro that keeps adding emulator cores and game integrations. This review covers what it does, how to install it, where the build breaks, and who should stay on gym-retro.
- Who is it for?
- Adopt Stable-Retro if you need Gymnasium-compatible retro environments, a broader emulator list than gym-retro ships, or a place to submit new game integrations, since gym-retro is described as being in maintenance and the README directs new PRs here. Stay away if you target Apple Silicon with Gameboy titles, Dreamcast on anything but Linux with ENABLE_HW_RENDER=ON, or Nintendo 64 on macOS, because the support table marks those paths as skipped or unavailable.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 13 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Stable-Retro Solves and Who It Is For
OpenAI's gym-retro let researchers turn classic console games into reinforcement learning environments, but the README states plainly that gym-retro is in maintenance now. Stable-Retro is the continuation: a fork that adds games, emulators and supported platforms, and that accepts pull requests for new games or features. The pitch is narrow and honest. If you already have RL infrastructure built on Gymnasium, Stable-Retro gives you environments that speak that API rather than one you have to shim.
The audience is specific. It is not for someone who wants to play Super Mario World with a gamepad. It is for people training agents who need deterministic, savestate-based resets at the start of levels, reward functions wired to in-game memory addresses, and episode termination conditions defined per game. The README describes exactly that: each game integration ships files listing memory locations for in-game variables, reward functions built on those variables, episode end conditions, savestates at level starts, and ROM hashes. That is a research artifact, not a frontend.
The category list gives a sense of the breadth. Platformers, fighters, sports, puzzle, shmups, beat-em-ups, racing, and an experimental RPG group that includes Pokemon Red and Final Fantasy. The README puts the total at over 1000 integrated games.
How the Emulator Cores and Game Integrations Fit Together
Stable-Retro is a C++ codebase with a Python package wrapped around it. The top-level repository layout shows cores/, src/, retro/, stable_retro/, third-party/, and a CMakeLists.txt at the root, with setup.py driving a CMakeBuild extension class. That means the Python wheel is not pure Python: building from source compiles emulator cores through CMake, and the setup.py file passes Python paths into CMake via flags such as -DPython_EXECUTABLE and -DPython_INCLUDE_DIR.
The build is configurable at configure time. The setup.py comments give the pattern for passing extra CMake flags during a pip install, and the README's platform table explains what those flags gate. Nintendo 64 cores are built by default when BUILD_N64=ON and OpenGL headers are available; if the headers are missing, the build skips the N64 core silently. Sega Dreamcast is only available when hardware rendering is enabled with ENABLE_HW_RENDER=ON, and the README states hardware rendering support is currently Linux-only. On Apple Silicon, the Gambatte Gameboy core is skipped by default in the CMake build.
That is the architecture in one sentence: a C++ emulator layer compiled per platform, a set of per-game integration files describing memory and rewards, and a Python layer that exposes each game as a Gymnasium environment. The environment name carries the system, as in Airstriker-Genesis-v0.
ROMs are not part of the package. The README says ROMs are not included and you must obtain them yourself, and that most ROM hashes come from No-Intro SHA-1 sums. Airstriker, a non-commercial Sega Genesis ROM by Electrokinesis, is included for testing, and the README points to a list of other included ROMs.
Installing Stable-Retro and Training on Airstriker-Genesis-v0
The package supports Python 3.10 through 3.14 and installs from PyPI. The README gives the one-line form first, and a git form for platforms where the wheel does not work.
pip3 install stable-retroIf that fails, the README falls back to installing straight from the repository.
pip3 install git+https://github.com/Farama-Foundation/stable-retro.gitYou only need a clone if you intend to integrate new ROMs, states or emulator cores, or edit an existing environment. That path is editable, so your local edits take effect.
git clone https://github.com/Farama-Foundation/stable-retro.git
cd stable-retro
pip3 install -e .If you want to pass CMake flags during that editable install, setup.py reads them from STABLE_RETRO_CMAKE_ARGS or CMAKE_ARGS. The comment in setup.py shows the shape of it.
CMAKE_ARGS="-DBUILD_N64=OFF -DENABLE_HW_RENDER=ON" pip3 install -e .For a first real run, the README walks through a PPO 'Nature CNN' model on Airstriker-Genesis-v0, whose ROM ships with the repo. On Ubuntu/Debian the system dependencies come first.
sudo apt-get update
sudo apt-get install python3 python3-pip git zlib1g-dev libopenmpi-dev ffmpegThen a Stable Baselines3 build that supports Gymnasium, followed by the training script from the examples directory.
pip3 install git+https://github.com/Farama-Foundation/stable-retro.git
pip3 install stable_baselines3[extra]
cd retro/examples
python3 ppo.py --game='Airstriker-Genesis-v0'Expect the first invocation to spend time on the emulator core and environment construction before any training log appears. For your own ROMs, drop them in the folder you want to import and run the import module; if the checksum matches a known hash, the ROM is filed into the related game folder.
python3 -m retro.import .Sega Saturn and Dreamcast titles additionally need a BIOS, and the README points to a BIOS name and checksum list in docs/core_bios.md. Platform-specific dependencies, including Ubuntu, WSL2 and Apple Silicon notes, live in docs/linux_installation.md and docs/macos_installation.md.
Where the Platform Matrix Breaks Down
The support table is the most useful page in the README because it is candid about holes. Dreamcast is Linux-only, and only when hardware rendering is on, so a Windows or macOS user who wants Dreamcast is out of luck regardless of how the rest of the stack behaves. Nintendo 64 is marked available on Linux and Windows but not Apple, and even on Linux and Windows it depends on OpenGL headers being present at configure time; without them the core is skipped rather than failing loudly, which means you can end up with a partial build and only notice when an environment fails to construct. Arcade machines are Linux and Windows only. Gameboy and Gameboy Color are listed as available on Apple with an asterisk: on Apple Silicon the Gambatte core is skipped by default in the CMake build.
The ROM situation is the second constraint, and it is not technical. Stable-Retro ships no game ROMs beyond Airstriker and whatever the included-ROMs list covers. The import path is hash-based, so an unverified dump or a regional variant with a different SHA-1 simply will not import. If your research depends on a specific revision of a title, check the hash file for the integration before you plan around it.
A third limitation is the RPG group. The README labels RPGs experimental, listing Pokemon Red, Legend of Zelda, Final Fantasy and Dragon Warrior. Treat those as integrations under development rather than finished reward definitions.
Finally, the documentation is unfinished by admission. The README says the docs site is work in progress, and the platform-specific guides are linked as separate files rather than folded into one reference. If you need an authoritative answer about a flag or a core, you will often be reading CMakeLists.txt and setup.py.
Stable-Retro Compared with Gym-Retro and Other Retro RL Environments
The obvious alternative is gym-retro, the project Stable-Retro forks. The difference is governance and velocity, not API shape. Gym-retro is described in the README as being in maintenance, and the README explicitly invites contributors to submit PRs with new games or features to Stable-Retro instead. So the practical distinction is that new emulator cores and new game integrations land in one repository and not the other. If you only need the games gym-retro already ships and you are happy with its API, the fork buys you nothing except a Gymnasium dependency.
That Gymnasium dependency is the second real difference. Stable-Retro's pyproject.toml declares gymnasium>=1.0.0 as a hard dependency, alongside pyglet>=1.5.27,<2 and farama-notifications. Environments that follow the Gymnasium interface interoperate with the current generation of RL libraries; the README's example uses Stable Baselines3 and notes you need a version that supports Gymnasium. If your training code is still written against the older gym API, moving to Stable-Retro is a migration, not a drop-in.
A third point of comparison is the integration tooling. Stable-Retro ships an Integration UI for adding new games, with a video playlist linked from the README, and the README notes that if your game is not included but its system is supported, the integration tool is provided to help add it. That is a different posture from a project in maintenance: the assumption is that you will extend it. The trade-off is that you inherit the build complexity of a C++ extension with per-platform core gating, which a pure-Python environment wrapper would not impose.
Licence, Maintenance and Upgrade Cost
Stable-Retro itself is MIT licensed, and pyproject.toml declares license = "MIT" with license-files covering LICENSE and LICENSES.md. The important detail is that MIT covers the project, not necessarily everything it links. The README directs readers to LICENSES.md for the licences of the individual cores, which means the emulator cores bundled or built alongside the Python package can carry different terms. If you are shipping a product rather than running experiments, read LICENSES.md core by core and check the terms of the ROMs you supply, since those are yours to obtain and are not distributed with the package. None of this is legal advice; it is a pointer to the files that matter.
On maintenance, the repository is not archived and the last push was on 2026-09-05, with releases at v1.0.1 on 2026-06-25, v1.0.0 on 2026-04-07 and v0.9.9 on 2026-02-15. The release cadence through 2026 is steady, and the project is governed by the Farama Foundation with a Discord and GitHub Issues for support.
The upgrade cost is concentrated in the native build. Because setup.py compiles through CMake and the platform table gates cores behind flags, a Python version bump or a new OS release can change which cores build. The wheel matrix in pyproject.toml targets cp310 through cp314 on manylinux_2_28 for x86_64 and aarch64 only, with no musl, so Alpine-based containers are not covered by the published wheels. Plan for a source build if you are outside that matrix.
Editorial conclusion
Adopt Stable-Retro if you need Gymnasium-compatible retro environments, a broader emulator list than gym-retro ships, or a place to submit new game integrations, since gym-retro is described as being in maintenance and the README directs new PRs here. Stay away if you target Apple Silicon with Gameboy titles, Dreamcast on anything but Linux with ENABLE_HW_RENDER=ON, or Nintendo 64 on macOS, because the support table marks those paths as skipped or unavailable. Before committing, verify three things on your own hardware: that pip3 install stable-retro resolves for your Python version (3.10 through 3.14), that your ROM SHA-1 sums match the hashes in the game integration files so python3 -m retro.import accepts them, and that the cores you need actually compile by checking the CMake flags your platform documents.
Frequently asked questions
What does retro mean in gaming?
Stable-Retro does not define the term; it uses retro in the sense of classic console and arcade systems, listing Atari 2600, NES, SNES, Nintendo 64, Nintendo DS, Gameboy, Gameboy Advance, Sega Genesis, Master System, CD, 32X, Saturn, Dreamcast, PC Engine and arcade machines among the emulated systems.
How many years until a game is considered retro?
The README gives no age threshold. It treats retro as a set of emulated systems and game integrations, and the supported game list includes titles from the 1980s through the 1990s across platformers, fighters, sports, puzzle, shmups, beat-em-ups and racing categories.
What are examples of retro games in Stable-Retro?
The README lists Super Mario World, Sonic The Hedgehog 2, Mega Man 2, Castlevania IV, Mortal Kombat Trilogy, Street Fighter II, NHL94, NBA Jam, Tetris, Columns, 1943, Gradius III, R-Type, Streets Of Rage, Double Dragon, Golden Axe, Final Fight, F-Zero and OutRun, among over 1000 integrated games.
Are 20 year old games retro in Stable-Retro?
The README does not answer this directly. It groups games by emulated system rather than by release year, and labels its RPG integrations (Pokemon Red, Legend of Zelda, Final Fantasy, Dragon Warrior) as experimental.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/farama-foundation-stable-retro)