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

tavyn-run

v0.1.0

Published

A wobbly-legged stickman endless runner for your terminal. Written in Rust, compiled to WebAssembly.

Readme

Tavyn Run

An endless runner for your terminal starring a stickman whose legs are far too thin. It's like the offline dino game, except the hero wobbles, stumbles, talks to himself, and keeps getting bonked by pigeons.

The game is written in Rust and compiled to WebAssembly. A small Node script runs it in your terminal, so one npm package works on Windows, macOS and Linux.

npx tavyn-run
 TAVYN RUN   SCORE 00024  HI 00000   SPEED 24
                                                       .-~~~-.
                   .-~~~-.
      \o/
       |
      / \                                     \_)
===============================================================
 .  `  ,. ,  ' .  `  ,. ,  ' .  `  ,. ,  ' .  `  ,. ,  ' .  `

How to play

| Key | Action | |---|---| | Space / ↑ / W | Jump. Press again in mid-air for a weaker, arm-flailing double jump | | ↓ / S | Duck. In mid-air it slams you down, and you're still ducking when you land | | P | Pause | | Q / Esc / Ctrl-C | Quit |

Terminals don't report key releases, so a duck lasts about half a second per press.

Obstacles

  • Banana peels, trash cans, wet floor signs and traffic cones: jump over them.
  • Open manholes: jump across the gap.
  • Pigeons at head height: duck under them.
  • Low pigeons: jump over them.

Chaos events. Every few hundred points one of these lasts 8 seconds:

  • HICCUPS: you hop on your own
  • OPPOSITE DAY: jump and duck are swapped
  • BLACKOUT: you can only see near yourself
  • PIGEON RAID: lots of birds
  • WINDY: the world speeds up and slows down

Pickups

  • [E] energy drink: steady legs and 4 s of invincibility.
  • {~} noodle legs: 5 s of floaty moon jumps.

Near-miss bonus: clearing an obstacle by a hair gives +25 PHEW!

Speed keeps rising up to a cap. Your best score is saved in ~/.tavyn-run.json. Set NO_COLOR=1 to turn colors off.

World leaderboard

The title screen shows the world top 5. If you make the top 10, the game-over screen asks for a name: type one and press Enter, or press Esc to skip.

What gets sent, and only when you press Enter: the name you typed, plus a replay of your run (the random seed and when you pressed jump or duck). The server re-plays the run to compute the score itself, so made-up scores don't work. Nothing else is sent; the only other request is fetching the board.

TAVYN_OFFLINE=1 turns all network access off, and TAVYN_SERVER=<url> uses a different server. If the server can't be reached, the game simply plays offline. The server lives in server/.

Development

You need Rust (with the wasm32-unknown-unknown target), wasm-pack, and Node 18 or newer.

rustup target add wasm32-unknown-unknown
cargo install wasm-pack

cargo run --release   # play the native build (fastest edit-play loop; offline only)
cargo test --workspace            # all tests, including a bot that checks every seed is survivable
wasm-pack test --node -- --test determinism   # same run must give identical results in WASM
npm run build         # compile to WebAssembly into pkg/
npm start             # play the WASM build, which is exactly what npm users get

cargo run -p tavyn-server                       # local leaderboard server
TAVYN_SERVER=http://127.0.0.1:8787 npm start    # play against it

If you change gameplay (physics, spawning, scoring), bump RULES_VERSION in src/game.rs. Replays recorded under old rules won't verify anymore, and tests/determinism.rs fails as a reminder.

Layout

src/
  game.rs       game state machine, spawning, scoring, collisions, chaos events
  player.rs     stickman physics (jump, flail-jump, duck, slam)
  obstacles.rs  obstacle kinds and hitboxes
  events.rs     chaos events and power-ups
  render.rs     character grid -> ANSI frame
  sprites.rs    all the ASCII art
  text.rs       death messages, mumbling, name cleaning
  rng.rs        tiny seeded RNG (keeps the engine deterministic and WASM-friendly)
  math.rs       platform-independent sine (gameplay math must match in WASM and native)
  replay.rs     re-simulate a recorded run (used by the server)
  bot.rs        autopilot used by tests
  wasm.rs       wasm-bindgen API used by js/cli.js
  main.rs       native terminal runner (crossterm)
js/cli.js       npm entry point: keyboard, frame loop, settings file, leaderboard requests
server/         leaderboard server (axum + SQLite) and deploy files
tests/          cross-platform determinism test

The engine is pure logic: hosts call press(key), tick(dt) and frame(cols, rows) and print the string it returns. The same code runs natively and in WASM, and every run is fully determined by its seed and inputs.

Publishing to npm

First set DEFAULT_SERVER in js/cli.js to your leaderboard's HTTPS URL. Then:

npm login
npm publish        # `prepack` runs `npm run build`, so pkg/ is always fresh

Use npm pack first to check exactly what gets shipped. It should be js/cli.js, pkg/tavyn_run.js and pkg/tavyn_run_bg.wasm, about 36 kB in total. Bump the version in both package.json and Cargo.toml before each release.