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

@wcstack/devtools

v1.24.0

Published

In-page DevTools overlay for wcstack. Inspect state trees, bindings/wiring and update timelines via the DevTools Hook Protocol - one script tag, no build step.

Readme

@wcstack/devtools

🤖 AI coding agents: This README is a package-level reference, not the primary entry point for building a wcstack application. If you have not already done so, first read the repository README and AGENTS.md, then use the wcstack-app skill.

In-page DevTools overlay for wcstack. One <script> tag adds a <wcs-devtools> overlay that lets you inspect state trees, see which DOM nodes each state path is wired to, and watch a live timeline of writes, update batches, and command/event-token emissions.

  • Zero dependencies, zero build. Connects to the page's wcstack runtimes only through the DevTools Hook Protocol (globalThis.__WCSTACK_DEVTOOLS_HOOK__) — it does not import @wcstack/state, and works even when multiple copies of a runtime are on the page.
  • Standards-first. The overlay is itself a custom element rendered in a closed world (Shadow DOM); it never touches the page's DOM, CSS, classes, or styles. Highlights are drawn as fixed-position overlay boxes.
  • Inert in production paths. With no devtools attached, the runtime cost of the instrumentation in @wcstack/state is a single null check per site; the overlay is only present when you add the script tag. SSR renders nothing.

Quick start

<!-- load BEFORE @wcstack/state so the wiring ledger is captured live -->
<script type="module" src="https://esm.run/@wcstack/devtools/auto"></script>
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>

Open the panel with the floating WCS badge or Alt+Shift+D.

The auto entry defines <wcs-devtools> and appends one to <body> if the page does not already contain one. To control placement/attributes, write the tag yourself:

<wcs-devtools open dock="right" hotkey="Ctrl+Shift+X" buffer="1000"
              hidden-states="analytics"></wcs-devtools>

Panes

| Pane | What it shows | |---|---| | State | Every <wcs-state> (per runtime source): top-level keys, expandable arrays/objects, computed getters. Click a value to edit it inline — the write goes through the normal reactive pipeline (set trap → update batch → DOM), so the page reacts exactly as if application code had written it. Click a path to highlight the DOM nodes bound to it. | | Wiring | The live binding ledger: property ← path@state rows per binding, with type badges (text / prop / for / …). Use ⌖ pick to click a page element and see only its bindings. Rows highlight their bound nodes on click. | | Timeline | A ring buffer (default 500) of write (with old value when available), batch (deduplicated update addresses per drain), command / event token emissions (with argument summaries and subscriber counts — zero-subscriber emissions get a warning badge, catching wired-before-whenDefined races), and state element registration. ⏸ pauses, 🗑 clears. |

Attributes

| Attribute | Default | Meaning | |---|---|---| | open | closed | Panel visibility (toggled by badge/hotkey) | | dock | bottom | bottom or right | | hotkey | Alt+Shift+D | Toggle shortcut; none disables | | buffer | 500 | Timeline ring-buffer capacity (read at connect) | | hidden-states | — | Comma-separated state names to hide (names starting with wcs-devtools are always hidden) |

Late attach

If devtools loads (or is injected) after bindings were built, past binding-added events are unrecoverable — the Wiring pane falls back to a declared view (re-scanning data-wcs attributes and wcs-* comments) and offers a reload link; everything else (state tree, editing, timeline from that point on) works fully. See protocol §6.

Notes & limitations

  • The panel repaints on requestAnimationFrame; in a hidden/background tab (where the overlay is invisible anyway) rendering pauses until the next frame.
  • While open, the docked panel covers part of the page — dock it to the other side or close it to interact with covered controls.
  • @wcstack/signals support is planned (the protocol reserves kind: "signals"); v1 covers @wcstack/state.

Programmatic use

The pieces are exported for building your own tooling on the same protocol:

import { DevtoolsCore, getOrCreateHookRegistry, formatValue, scanDeclaredBindings }
  from "@wcstack/devtools";

const core = new DevtoolsCore({ timelineCapacity: 200 });
core.connect();
core.onChange((kind) => { /* "sources" | "roster" | "wiring" | "timeline" */ });
core.getRoster();      // observed <wcs-state> elements
core.getTimeline();    // ring buffer snapshot

License

MIT