npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

asobou

v0.2.2

Published

Play retro games directly in your terminal

Readme


[!note]

The game used in the demonstration above is Alter Ego.

Overview

Asobou is a command-line tool that allows you to play retro games directly in your terminal. Simply run:

asobou 'Super Mario Bros.zip'

Asobou detects the system, ensures a suitable emulator is available, picks the best renderer your terminal supports, and starts the game.


If you do not have a game file handy, you can use asobou brew to try one from the internet:

asobou brew indivisibleonnes.nes

Or use npx to run Asobou without installing it globally:

npx asobou brew indivisibleonnes.nes

This loads the game Indivisible on NES from https://github.com/retrobrews/nes-games/blob/master/indivisibleonnes.nes and starts it.

Prerequisites

  • Asobou's default renderer works with terminals that support Terminal graphics protocol. Here is a non-exhaustive list of supported terminals (sorted alphabetically):

    Kitty has the best overall experience for running Asobou.

  • Asobou requires an active internet connection to download emulator binaries from https://buildbot.libretro.com/ when needed.

  • Asobou requires you to provide the game (ROM file), as it does not bundle any game content.

Installation

You do not need to install anything if you just want a quick try — run it with npx:

npx asobou

From npm:

npm install asobou -g

From crates.io:

cargo install asobou

With cargo-binstall:

cargo binstall asobou

With mise:

mise use github:arianrhodsandlot/asobou -g

You can also manually download the binary from the releases page. It is a standalone executable that does not require any additional dependencies.

Usage

Here are some typical usage examples:

Start a game

asobou 'Super Mario Bros.zip'

Start a game and render it as ASCII characters

asobou 'Streets of Rage 2.md' --renderer=ascii

Run with an explicit core

asobou 'Super Castlevania IV.zip' --core=snes9x

Load a save state at startup

asobou 'Super Metroid.sfc' --state=~/backup.state

Load the latest managed state at startup

asobou 'Super Metroid.sfc' --resume

Install a libretro core

asobou core install genesis_plus_gx

Set a configuration value

asobou config set rewind.buffer_size_mb 64

List saved states, filtered

asobou state list 'Pokemon Emerald.gba' --core=mgba

Download and play a homebrew game from https://retrobrews.github.io/

asobou brew flappybird.nes

Print help

asobou --help

Configuration

Asobou loads the first applicable config path:

  1. The exact path in the ASOBOU_CONFIG environment variable
  2. $XDG_CONFIG_HOME/asobou/config.toml
  3. ~/.config/asobou/config.toml on Linux and macOS
  4. %APPDATA%\asobou\config.toml on Windows

The config file is optional; omitted settings keep their defaults. Explicit command-line values override configuration values.

[audio]
muted = false # Disable game audio when true

[display]
fps = 60 # Maximum terminal refresh rate, from 1 to 240
renderer = "auto" # auto, graphic, block, ascii
primary_screen = false # Use the primary buffer when true

[input]
# Each input takes one standalone key, and a key cannot be assigned to more than one input.
# Keys follow the RetroArch conventions. Printable characters are written directly; the other supported names are:
# space enter escape tab backspace
# up down left right home end pageup pagedown insert del
# f1 through f24
# num0 through num9
# period comma slash minus equals leftbracket backslash rightbracket
# backquote quote semicolon tilde
# capslock numlock print_screen scroll_lock pause menu
# shift rshift ctrl rctrl alt ralt
# left-super right-super left-hyper right-hyper left-meta right-meta iso-level-3-shift iso-level-5-shift
# numpad-0 through numpad-9        keypad0 through keypad9
# numpad-decimal  kp_period        numpad-divide  divide
# numpad-multiply  multiply        numpad-subtract  kp_minus
# numpad-add  kp_plus              numpad-enter  kp_enter
# numpad-equal  kp_equals          numpad-comma
# numpad-up  numpad-down  numpad-left  numpad-right
# numpad-home  numpad-end  numpad-page-up  numpad-page-down
# numpad-insert  numpad-delete  numpad-begin
up = "up"
down = "down"
left = "left"
right = "right"
a = "x"
b = "z"
x = "s"
y = "a"
start = "enter"
select = "rshift"
l = "q"
r = "w"
quit = "escape"
rewind = "r" # Hold to rewind
save_state = "f2" # Save a new state to `data_dir`
load_state = "f4" # Load the newest state
# Optional buttons, unbound by default:
# l2 = "e"
# r2 = "u"
# l3 = "t"
# r3 = "y"

[paths]
# Data lives in `$XDG_DATA_HOME/asobou` and cache in `$XDG_CACHE_HOME/asobou` by
# default (`~/Library/Application Support/asobou` and `~/Library/Caches/asobou` on
# macOS, `~/.local/share/asobou` and `~/.cache/asobou` on Linux). `paths.data_dir`
# and `paths.cache_dir` override the base directory: cores and save states go
# under `data_dir/cores` and `data_dir/states`, brew downloads under
# `cache_dir/brew`. Values must be absolute or start with `~/`. These settings
# take precedence over the `XDG_DATA_HOME` and `XDG_CACHE_HOME` environment
# variables, which are used only when the corresponding key is unset (an empty
# variable counts as unset).
cache_dir = "~/.asobou/cache" # Override the cache base (brew downloads)
data_dir = "~/.asobou/data" # Override the data base (cores, save states)

[rewind]
# Rewind steps back while the rewind key is held. A higher `granularity` uses
# less memory and CPU but rewinds in coarser steps; once `buffer_size_mb` is
# reached the oldest snapshots are dropped. Disabling rewind frees the key for
# other bindings and hides it from the on-screen status line.
enabled = true # Snapshot-based rewind
granularity = 2 # Frames between snapshots
buffer_size_mb = 20 # Memory cap for stored snapshots

[state]
save_on_exit = false # Save a state when exiting cleanly
resume = false # Resume the last state on startup

[status]
# The status text is centered and dimmed over the bottom of the rendered frame.
# Set `status.enabled` to `false` to hide both lines, or toggle `gamepad` and
# `controls` independently. Save and load notifications remain visible when the
# keybinding status is hidden. Notifications are anchored to the bottom-left and
# do not change the centered keybindings' position.
controls = true # Show save, load, rewind, and exit on the lower line
enabled = true # Show the on-screen keybinding status
gamepad = true # Show gamepad inputs on the upper status line

Supported platforms

Many more cores are available at https://buildbot.libretro.com/. The following platforms and default cores are tested and cover most popular systems.

| Platform | Default Core | | ---------------------- | --------------- | | Atari 2600 | stella | | Atari 5200 | a5200 | | Atari 7800 | prosystem | | Atari Lynx | handy | | Game Boy | gambatte | | Game Boy Advance | mgba | | Game Boy Color | gambatte | | Game Gear | genesis_plus_gx | | Megadrive / Genesis | genesis_plus_gx | | NES / Famicom | nestopia | | Neo Geo Pocket (Color) | mednafen_ngp | | Super Nintendo | snes9x | | WonderSwan (Color) | mednafen_wswan |

Other platforms and cores not listed here may work with Asobou too, but are not tested.

Cores that require GPU acceleration do not work with Asobou.

Under the hood

Asobou is a libretro frontend: the emulation itself is performed by libretro cores, shared libraries such as nestopia_libretro.so on Linux, snes9x_libretro.dylib on macOS, or mgba_libretro.dll on Windows. Asobou locates, loads, and drives these cores, turning their output into something a terminal can display.

Emulation and rendering run on separate threads: the emulation thread captures video only when the renderer requests a frame, and hands the latest frame to the render thread through a mailbox. The active renderer then draws it:

  • graphic — sends the frame as raw RGB data, using zlib compression when supported, via the Terminal graphics protocol
  • block — downsamples the frame into colored half-block cells (▀)
  • ascii — maps pixel brightness to ASCII characters

Credits

Alternatives

Related

You might also be interested in my other project: Nostalgist.js, a JavaScript library used for running emulators of retro consoles inside browsers.

License

MIT