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

@terminalika/pi-play

v0.1.1

Published

terminalika inside pi: retro games in an overlay that pause themselves the moment the agent finishes or needs you.

Readme

pi-play

terminalika inside pi: /play opens a game over the conversation, and it pauses the moment pi is waiting for you

terminalika as a pi package: the retro games from terminalika-core, running in an overlay inside pi, that pause themselves the moment pi finishes and is waiting for you. No standalone binary, no second pane.

pi install npm:@terminalika/pi-play

Then, while pi works:

/play            pick a game
/play snake      or name one: snake, tetris, 2048, mines
/play tetris     while snake is on: swap it (asks first, until you say don't)
/play stop       end the game

Arrows/WASD move, SPACE pauses, R resets. When pi settles (its turn is over, it is waiting on you) what happens to a running game is asked once, on the first /play, and remembered in the terminalika config dir (pi.json):

  • Pause the game — freeze it with a notice in pi's colour; resume with SPACE (default),
  • Settle the game — the game settles too: parked, hidden, the keyboard back with pi, and a toast pointing at /play,
  • Don't pause — keep playing; pi settling changes nothing.

Skipping the question (Esc) keeps the default for that run and offers it again next time. The file can be edited by hand:

{ "auto_pause": "pause" }

Going back to pi never ends the game: ESC parks it - paused, hidden, the editor has the keyboard again and the status line remembers it - and /play brings it back exactly where it was. The only thing that ends a game is /play stop.

Changing games: /play <other> from the editor, or alt+g from either side - it opens the picker with the game that is on listed first (so Enter returns to it); in the game it parks first, and cancelling brings the same game back. Since swapping closes the game that is on, it asks Yes / No / Yes, and don't ask again; the last one is remembered in pi.json as "confirm_switch": false.

On a Mac every alt+… above reads option+… - in the hints, the toasts and the status line. The key is the same one.

Try it without installing: pi -e /path/to/pi-play.

How it works

This is a thin pi launcher for terminalika-core, the same way the CLI and the website are thin launchers: the games are written once, in Go.

terminalika-core (Go) ──GOOS=js──▶ wasm/terminalika.wasm
                                        │  tcell's web-screen protocol:
                                        │  Go calls resize/clearScreen/drawCell/show,
                                        │  registers onKeyEvent, exposes tkPause/tkResume/tkQuit
                                        ▼
src/worker.ts               the game's thread: screen.ts keeps the cell
  (screen.ts, runtime.ts)   grid, runtime.ts runs the wasm; every frame is
                            posted to the main thread as ANSI lines
                                        │
                                        ▼
src/host.ts                 main thread: keeps the latest frame for a pi
                            overlay component (ctx.ui.custom({ overlay:
                            true })), relays keys (src/keys.ts)
                                        │
                                        ▼
extensions/terminalika.ts   /play, and pi.on("agent_settled") → tkPause.
  • Overlay, not a pane. The game floats over the conversation; pi's own DOOM example is proof the overlay can carry real-time rendering. It takes exactly as many rows as the game says it needs (core.Sized: board, status line above, hint lines below), each game reporting its own number, and the full width of the terminal: pi splices an overlay into each row after the text to its left, measured with its own width tables, and a terminal that draws an emoji one cell differently would shift that row.
  • Its own thread. The wasm runs on a worker thread (src/worker.ts); pi rendering a streaming answer on the main thread cannot starve the game's ticks or its held-key timers. The main thread only keeps the latest frame (src/host.ts).
  • Events come straight from pi. No session-file tailing: agent_settled is the moment pi will not continue on its own. Desktop notifications are not this package's job; pi has extensions for that.
  • Key releases. Under a terminal that speaks the kitty keyboard protocol pi reports releases and held keys feel exact; elsewhere the engine synthesises releases from auto-repeat, like the CLI does.

Not yet: high scores (the wasm has no filesystem).

Layout

extensions/terminalika.ts   the pi extension
src/                        the host: worker + host (the game's thread and the main thread's
                            view of it), screen (cell grid → ANSI), runtime (wasm_exec), keys
go/                         the Go side: main + engine port (pause notice, held keys)
wasm/                       terminalika.wasm + wasm_exec.js, built from go/ (committed)
scripts/build-wasm.sh       npm run build:wasm  (Go 1.24+; prefers a sibling ../terminalika-core)
scripts/smoke.ts            npm run test:wasm   (headless: every game renders, pauses, exits)

Requirements

pi 0.84+ (agent_settled, overlays). Node 22+ or Bun for the host; the package ships the wasm, so no Go toolchain is needed to use it.