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

@debuffjp/dev

v0.15.0

Published

Dev-only inspection hooks for debuff games, for tools and AI agents

Readme

@debuffjp/dev

Dev-only inspection and control hooks that let browser tools, the debuff CLI and AI agents see and drive a running game.

import { devTools } from "@debuffjp/dev";

if (import.meta.env.DEV) game.use(devTools({ input }));

Bundlers drop the call from production builds, and debuff build fails if it leaks.

window.__DEBUFF_DEV__

All arguments and return values are JSON-serialisable.

| Method | Returns | | --- | --- | | state() | { scene, tick, time, frozen, stats, camera, state, pluginNames, plugins }. camera is the centre, zoom and view size in world units, state is the active scene's inspect(), and plugins holds game.inspect snapshots | | step(n) | pauses, advances n fixed steps, returns state() | | pause() / resume() / speed(scale) | live control; state().pausedBy says who paused | | frames(n) | the latest n frame breakdowns: interval, update and render ms, catch-up steps, quads, draw calls, long tasks | | notes() | moments flagged in the overlay, with state and frames | | params() / setParam(group, key, value) | typed parameter schemas and values | | press(code) / release(code) | keyboard | | tap(x, y) / pointerDown / pointerMove / pointerUp | pointer, in logical coordinates | | errors() | runtime errors since load, explained: kind (your-code, debuff-usage, debuff-bug, outside), source-mapped where, hint, count | | capture() | PNG data URL of the current frame | | keepForReload() | save the session for a state-preserving reload; the debuff dev client calls it just before a code change reloads the page | | luminance(cols, rows, region?) | the current frame's WCAG relative luminance on a grid, for the scenario flash and contrast checks | | events(sinceTick?) | the latest game.emit calls with tick and detail; state().events counts them by name | | rewind(tick) | reload and replay this session's inputs to tick, then pause: the exact state at that moment. Within the known session you can go forward again until new play branches off. Live games only | | replay(toTick?) | everything played since load (keys, pointer, param changes) up to toTick, as a scenario that replays it exactly, plus warnings for anything it can't reproduce. Needs devTools({ input }) |

Overlay

devOverlay() adds a panel. The backquote key hides it, and the ▾ button (or double-clicking the header) collapses it to a single bar with fps, an error count and the agent badge. The panel remembers whether it's collapsed and which tab is open.

The toolbar has pause, step, speed (1x, ½×, ¼×), snap (download the current frame as a PNG) and restart (re-enter the current scene). Below it are four tabs:

  • perf: a frame graph coloured by health: lime is on time, amber is a little late (normal display jitter) and red is a dropped frame. Update and render time are stacked inside each bar. A summary shows your headroom and whether recent dropped frames came from the game's own work or from outside it (GC, the browser, other tabs). Click a bar to pause and inspect that frame with a plain-words diagnosis, or tick pause on dropped frame. Phases also appear as debuff:update and debuff:render in the browser profiler.
  • tune: sliders for every game.params group. Values you've changed from their defaults turn amber. Double-click a name to reset it, and copy changes copies just your changes, ready to paste into the param definitions.
  • state: your scene's inspect() data and plugin snapshots, updating live.
  • log: runtime errors, each labelled with whose problem it is (your code, a call debuff rejected, a debuff bug, or something outside the game), with a link that opens the exact source line in your editor, a hint, and a report link for debuff bugs. Also an activity log of who changed what (you, an agent or a scenario) with undo, and notes you can flag for agents. save replay and copy replay turn the session so far into a scenario that debuff scenario plays back exactly, and save as scenario writes it to scenarios/ (through debuff dev) with a capture at the end, as a regression test. The timeline slider rewinds: drag to any tick and the page reloads, replays your inputs to that tick and pauses there. Drag forward again to return, until you play on from the earlier point.

Keep your place on reload

Under debuff dev, editing your code no longer sends you back to the start. Just before the page reloads, the dev tools save the session's inputs. The new code then replays them to the tick you were on (without drawing, typically a few milliseconds per hundred ticks), and the game carries on running, or stays paused if it was paused. The log says how long the replay took.

Because the inputs are replayed with the new code, a change to how the game plays shows up right where you were: lower the run speed and the player is where they'd be at the new speed. Keys you were holding are let go after the replay. Pass devTools({ input, keepState: false }) to turn it off.

Agent link

Under debuff dev, the page listens for commands from @debuffjp/mcp over the dev server, so agents work on the game you're looking at. Pass agentLink: false to opt out.

Open the page with ?debuff-scenario to stop the loop so time advances only through step(). debuff scenario uses this mode.