NES emulator extension for pi
npm install @tmustier/pi-nesPlay NES games in your terminal. A pi extension that runs a full NES emulator with Kitty graphics support.
``bash`
pi install npm:@tmustier/pi-nes
Or from git:
`bash`
pi install git:github.com/tmustier/pi-nes
`bash`
/nes # Pick a ROM from your library
/nes ~/roms/smb.nes # Load a specific ROM
On first run, you'll be prompted to set your ROM directory and display quality. When launching /nes without a path, type to filter the ROM list while you navigate.
| Action | Keys |
|--------|------|
| D-pad | Arrow keys or WASD |
| A button | Z |
| B button | X |
| Start | Enter or Space |
| Select | Tab |
| Action | Key |
|--------|-----|
| Detach (keep running) | Ctrl+Q |
| Quit | Q |
Tip: Detach with Ctrl+Q to return to pi, then run /nes to reattach to your game.
| Command | Description |
|---------|-------------|
| /nes | Pick a ROM or reattach to running session |/nes
| | Load a specific ROM file |/nes config
| | Quick setup (ROM directory + audio) |/nes-config
| | Toggle audio, quality, and display style + advanced options |/nes debug
| | Show FPS and memory stats |
Config is stored at ~/.pi/nes/config.json. Use /nes config for quick setup (ROM dir + audio), or /nes-config to toggle audio/quality/style inline and access advanced options.
`json`
{
"romDir": "/roms/nes",
"saveDir": "/roms/nes/saves",
"renderer": "image",
"imageQuality": "balanced",
"videoFilter": "ntsc-composite",
"enableAudio": false,
"pixelScale": 1.0,
"keybindings": {
"up": ["up", "w"],
"down": ["down", "s"],
"left": ["left", "a"],
"right": ["right", "d"],
"a": ["z"],
"b": ["x"],
"start": ["enter", "space"],
"select": ["tab"]
}
}
| Option | Default | Description |
|--------|---------|-------------|
| romDir | /roms/nes | Where to look for ROM files |saveDir
| | /roms/nes/saves | Where to store battery saves (defaults to ) |renderer
| | "image" | "image" (Kitty graphics) or "text" (ANSI) |imageQuality
| | "balanced" | "balanced" (30 fps) or "high" (60 fps) |videoFilter
| | "ntsc-composite" | "off", "ntsc-composite", "ntsc-svideo", "ntsc-rgb" |enableAudio
| | false | Enable audio output (requires native core built with audio-cpal) |pixelScale
| | 1.0 | Display scale (0.5–4.0) |
videoFilter applies a lightweight CRT/NTSC-inspired pass (horizontal bleed + scanlines). It runs in the native core and is optional.
Battery-backed SRAM is saved to where the hash is derived from the full ROM path to avoid collisions. Old files are ignored.
Saves are flushed on quit and periodically during play.
Best experience: a Kitty-protocol terminal like Ghostty, Kitty, or WezTerm (image protocol + key-up events).
- Kitty-protocol terminals — Full graphics via image protocol (shared memory or file transport)
- Other terminals — Falls back to ANSI half-block characters (▀▄)
Set "renderer": "text" if you prefer the ANSI renderer or have display issues.
- Audio is opt-in — Requires building the native core with audio-cpal and setting enableAudio: true
- No auto-save — Save manually just like you would with the original NES (battery-backed SRAM)
- nes_rust is vendored under extensions/nes/native/nes-core/vendor/nes_rust.scripts/update-vendor-nes-rust.sh
- Fork: https://github.com/tmustier/nes-rust (upstream: https://github.com/takahirox/nes-rust)
- Update helper:
---
Requires Rust toolchain (cargo + rustc).
`bash
git clone https://github.com/tmustier/pi-nes
cd pi-nes
npm install
Run locally:
`bash
pi --extension /path/to/pi-nes
``