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

@contextune/sdk

v0.2.0

Published

Network-intercept behavioural SDK: captures analytics events at the transport layer and surfaces a structured snapshot for AI agent context.

Readme

@contextune/sdk

Network-intercept behavioural SDK: captures analytics events at the transport layer and surfaces a structured snapshot for AI agent context.

Contextune helps customer-facing AI agents respond better by giving them behavioural context they normally can't see. It captures a live view of what the user is doing in the browser, the pages they visit, where they click and scroll, where they hesitate, and injects it into the agent's context window. The agent can then infer intent from behaviour instead of from the latest message alone. It's built for cases where what the user just did on the page changes what the agent should say: travel concierges, in-product support agents, and ecommerce shopping assistants.

@contextune/sdk is the client-side piece. It maintains that behavioural profile in the browser and exposes it as a structured snapshot you can drop into a prompt. It runs in plain JavaScript or TypeScript with no framework or model assumptions, makes no network requests of its own, and keeps the snapshot in memory until you read it.

The snapshot captures signals an agent can't infer from the message alone: the running event log with elapsed time between events, scroll depth, rage clicks, the marketing parameters that brought the user in, and device context.

contextune.com · docs.contextune.com

Install

npm install @contextune/sdk

No peer dependencies.

Use

import { Contextune } from "@contextune/sdk";

Contextune.init({ source: "ga4" });

// Later, at the point your agent is invoked:
const snapshot = Contextune.getSnapshot();
// Inject `snapshot` into the agent's system prompt or first message.

getSnapshot() returns a structured object:

{
  event_log: [
    { name: 'page_view', elapsed_s: 0 },
    { name: 'add_to_cart', elapsed_s: 34, properties: { item: 'field-jacket-m' } },
    { name: 'checkout_started', elapsed_s: 67 },
  ],
  marketing_params: {
    utm_source: 'google', utm_medium: 'cpc', utm_campaign: 'summer',
    utm_term: null, utm_content: null,
    referrer: 'https://www.google.com/',
    landing_page: 'https://shop.example.com/?utm_source=google',
  },
  device_info: {
    user_agent: '...',
    viewport_w: 1440, viewport_h: 900,
    language: 'en-GB',
    platform: 'MacIntel',
    device_type: 'desktop',
  },
}

Two modes

Network-intercept mode

Pass source to tap an existing analytics stream. The SDK patches fetch, sendBeacon, and XMLHttpRequest, filters traffic from the configured provider, and extracts structured events without any changes to your existing analytics setup.

Contextune.init({ source: "ga4" }); // tap GA4 traffic
Contextune.init({ source: "segment" }); // tap Segment traffic
Contextune.init({ source: "mixpanel" }); // tap Mixpanel traffic

Direct-call mode

Omit source entirely. No network interception; only track() and page() calls are captured. Use this when you want Contextune itself as the lightweight analytics layer.

Contextune.init();

Contextune.track("filter-applied", { facet: "size", value: "M" });
Contextune.track("checkout-started", { cart_value: 129 });

Options

Contextune.init({
  // 'ga4' | 'segment' | 'mixpanel' — tap an existing analytics stream.
  // Omit for direct-call mode (only track()/page() are captured).
  source: "ga4",

  // Cap on the rolling event log. Default 50.
  eventLogSize: 50,

  // Event log lifetime.
  // 'navigation' (default) — cleared on page reload.
  // 'ct-session' — survives reloads; scoped to 30 min of inactivity.
  persistence: "navigation",

  // Context blocks. Both default to true.
  context: {
    extras: {
      marketing: true, // UTM params, referrer, landing page
      device: true, // viewport, language, platform, device type
    },
  },

  // DOM-derived behavioural signals (optional).
  tracking: {
    scroll: true, // fire 'scroll' at 25/50/75/100% depth milestones
    rageClicks: true, // fire 'rage_click' on ≥3 clicks within a 1-second window
  },
});

Subscribing to events

React to events as they arrive rather than polling getSnapshot().

const unsubscribe = Contextune.subscribe(filter, handler);

handler receives two arguments:

| Argument | Type | Description | | -------- | -------------------- | ------------------------------------------------------------------ | | entry | EventLogEntry | The event that just landed | | state | ContextuneSnapshot | Full snapshot captured immediately before this event was added |

filter controls which events trigger the handler:

// Fire on every event
const unsubscribe = Contextune.subscribe("event", (entry, state) => {
  console.log(entry.name, entry.elapsed_s);
});

// Fire only when the predicate returns true
const unsubscribe = Contextune.subscribe(
  (entry) => entry.name === "checkout_started",
  (entry, state) => sendAgentContext(state),
);

// Cleanup — call the returned function to detach
unsubscribe();

Subscriptions are framework-agnostic. They work in vanilla JS, React, Vue, or any other environment. Multiple subscribers can be active simultaneously. All are cleared automatically on Contextune.destroy().

If subscribe is called before init(), the returned unsubscribe is a no-op.

Lifecycle

  • Contextune.init(options?): idempotent singleton. Returns the existing instance if already initialised. Call destroy() first to re-initialise with different options.
  • Contextune.getSnapshot(options?): returns the current snapshot, or null before init().
  • Contextune.track(name, properties?): push a named event into the log directly.
  • Contextune.page(url?): record a page view. Call on each SPA route change.
  • Contextune.subscribe(filter, handler): react to events as they arrive. Returns an unsubscribe function.
  • Contextune.clear(): empty the event log (in memory and, under ct-session, its persisted copy) while keeping the SDK running — patches, subscribers, and the session clock stay intact.
  • Contextune.destroy(): full teardown — removes transport patches, clears the buffer and all subscribers, resets the singleton, and under ct-session removes the stored log and expires the cookie so the profile can't be recovered.

Page views (single-page apps)

Call Contextune.page() on every route change so the event log reflects navigation:

import { Contextune } from "@contextune/sdk";

// e.g. in a Next.js usePathname() effect or router subscription:
Contextune.page();
// or pass an explicit URL to record a pre-redacted path:
Contextune.page("/checkout/confirmation");

Snapshot formats

getSnapshot() accepts an optional format:

Contextune.getSnapshot(); // ContextuneSnapshot object (default)
Contextune.getSnapshot({ format: "js" }); // same — explicit
Contextune.getSnapshot({ format: "json" }); // JSON string
Contextune.getSnapshot({ format: "toon" }); // TOON string (token-optimised for LLMs)

TOON (Token-Oriented Object Notation) is a compact, flat serialisation designed to minimise token usage in LLM prompts. Flat blocks render as YAML-style key: value pairs; the event log renders as a CSV table.

Privacy

The SDK never makes a network request of its own. The event log redacts properties named password, email, credit_card, cvv, ssn, and any key matching /(password|secret|token|api[_-]?key|jwt|session)/i. URL-shaped values have credential-bearing query parameters stripped and UUID path segments replaced with [id]. Redaction is applied before any event enters the ring buffer.

Bundle size

~13 KB minified / ~4–5 KB gzipped. No peer dependencies.

Supported browsers

All evergreen browsers ✅

Via CDN (no bundler):

<script src="https://unpkg.com/@contextune/sdk"></script>
<script>
  Contextune.init();
  const snapshot = Contextune.getSnapshot();
</script>

Via package manager (bundled apps):

npm install @contextune/sdk

Contributing

This repository is a read-only mirror. The SDK is developed in a private monorepo and published here on each release, so changes land as Release vX.Y.Z commits rather than direct merges. Issues and pull requests are still welcome. See CONTRIBUTING.md for how they get incorporated.

License

MIT. See LICENSE. Copyright 2026 Reidworks.