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

@characterxyz/web

v0.10.0

Published

Character XYZ for the web, headless: sessions, streamed chat, voice calls with a fair queue. Framework-free, zero dependencies.

Readme

@characterxyz/web

The headless Character XYZ SDK: sessions, streamed chat, real-time voice calls and the call queue, with no UI. Build your own interface on the same calls the ready-made widget uses. Framework-free, zero dependencies, 8 KB gzipped.

Want the ready-made widget instead? Use @characterxyz/widget (any site) or @characterxyz/react.

npm install @characterxyz/web
import { CharacterXYZ } from '@characterxyz/web';

const cx = await CharacterXYZ.init({ publishableKey: 'cxyz_pk_live_…' });
cx.chat.on('messages', render);           // streams as the reply is written
await cx.chat.send('Hello!');

callButton.onclick = async () => {        // from a click: it needs the microphone
  const call = await cx.startCall({ autoAccept: true });
  call.on('state', (s) => show(s.phase, s.position, s.etaSeconds));
  call.on('caption', (c) => caption(c.role, c.text));
};

When every line is busy, a call waits in a first-come queue with its place and an estimate; the visitor can keep chatting meanwhile.

Context, events and actions

The page and the agent talk in both directions. Three layers, one session:

// 1. CONTEXT IN — who this is and what is true now. Level-triggered: it stays
//    in scope for every later turn until changed. Scope: visitor.*, context.*.
await cx.identify({ id: 'u_42', email: '[email protected]', name: 'Asha', traits: { plan: 'pro' } });
await cx.setContext({ page: '/pricing', cart: { items: 2, value: 4200 } });

// 2. EVENTS IN — something the visitor DID. Only names the agent's graph
//    declares are accepted. Fire-and-forget: do not await it.
void cx.track('pricing_viewed', { plan: 'pro' });
//    Scope in the graph: {{event.name}}, {{event.data.plan}}.
//    With `openChat` on the node, the widget opens itself for the reply.

// 3. ACTIONS OUT — the graph asks the page to do something.
const off = cx.registerAction('openCart', async ({ itemId }) => {
  await cart.open(String(itemId));
  return { opened: true, count: cart.count };
});

The graph side is two nodes beside the existing ones: On Site Event (one per event name; the name is the allowlist, with an optional data shape and a Send test event button in the console) and Client Action (pick an action the page registered; its answer resumes down done or failed, and result is readable after the node).

cx.track sends an idempotency id and keepalive, so a retry or a click that navigates away is still one event. An awaited page action is a two-phase handshake on the same HTTP connection: the walk suspends, the SDK runs your handler, posts the result, and the reply comes back. Nothing is polled.

Options

| Option | | |---|---| | publishableKey | cxyz_pk_live_…, safe in the page; works only from the key's allowed sites | | getSessionToken | For signed-in visitors: returns a session your server minted with @characterxyz/server | | agentId | Which of the key's agents. Default: the key's first | | storage | local (remember the anonymous visitor, default) · memory · your own store |

Create keys and choose the sites they may run on in Character XYZ › Settings › Developers.

License

MIT