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

@tracer-llm/watch

v0.1.0

Published

Local-first, OpenTelemetry-GenAI-aligned LLM trace recording. Watch any model call with a wrapper, a decorator, or an async span. Zero runtime dependencies.

Readme

@tracer-llm/watch

Local-first, OpenTelemetry-aligned LLM trace recording for JavaScript / TypeScript.

Watch any model call in your pipeline with a wrapper, a method decorator, or an async span. No key, no account, nothing leaves your machine by default: traces are appended to ./.tracer/watch/<name>.jsonl.

  • Standards-native schema: every watched call is recorded as a span following the OpenTelemetry GenAI semantic conventions (gen_ai.*), so a record is portable to any OTel-aware backend. No proprietary schema.
  • Zero runtime dependencies. Node stdlib + the global fetch only.
  • Prod-safe: telemetry never throws into, or adds latency to, the host call. Cloud sends are batched on a timer; a slow or down endpoint can never block your function, and a thrown request is swallowed.

Install

npm install @tracer-llm/watch

Usage

import { watch } from "@tracer-llm/watch";

const w = watch("support_classifier", { system: "provider-x", model: "model-x" });

1. Wrap a function

The watcher is callable: pass it a function and it returns a wrapped one. The first argument is recorded as the input, the return value as the output. If the return value looks like a provider response (see below) the model, tokens, finish reason and tool calls are auto-captured.

const classify = w(async (ticket: string) => {
  const resp = await callModel(ticket); // any provider response object
  return resp;
});

await classify("how do I reset my PIN?");

2. Method decorator

class Support {
  @w.llm
  async answer(question: string): Promise<string> {
    return await callModel(question);
  }
}

(Requires "experimentalDecorators": true in your tsconfig.json.)

3. Async span

For full control, run a body inside a span and enrich it through the handle:

await w.span(
  { input: "how do I reset my PIN?", userId: "u1", sessionId: "s1", metadata: { plan: "pro" } },
  async (s) => {
    const resp = await callModel("...");
    s.record(resp);                                   // auto-extract from a response
    s.setOutput("...");                               // or set output text directly
    s.setUsage({ prompt: 5, completion: 2, costUsd: 0.001 });
    s.setParams({ temperature: 0.2, maxTokens: 64 });
    s.addToolCall("get_balance", { acct: 1 }, { bal: 42 });
    s.setAttribute("experiment", "A");
  },
);

Spans opened inside another span inherit the parent's traceId and point at it via parentSpanId, forming a trace tree (tracked with AsyncLocalStorage).

Free Tracer Cloud streaming (one line)

Set one environment variable and your watched traffic streams to the dashboard within seconds. No code change:

export TRACER_CLOUD_KEY=trobs_...

or pass it inline:

const w = watch("classifier", { cloudKey: "trobs_..." });

Sinks

| Sink | What it does | Turned on by | | ----------------- | ----------------------------------------------------------------------- | -------------------------------------------------------- | | LocalFileSink | Append spans as JSONL to <dir>/<name>.jsonl. No network, no key. | Default, always on. | | TracerCloudSink | Batch + stream spans to the free Tracer Cloud observability. | cloudKey option or TRACER_CLOUD_KEY. | | OTLPSink | POST an OTel GenAI-shaped payload to any OTLP/HTTP backend. | TRACER_WATCH_OTLP_ENDPOINT (+ TRACER_WATCH_OTLP_HEADERS). | | MultiSink | Fan-out to several sinks at once. | Composed automatically when more than one is configured. |

sinkFromEnv(name, cloudKey?) composes the chain: local file + cloud (if a key is set) + OTLP (if an endpoint is set).

The cloud sink routes by key prefix, matching the two product paths:

  • trobs_* (workspace ingest key) -> POST /v1/observe, body { events }
  • otherwise (per-tracer gateway) -> POST /v1/ingest, body { source, events }

Provider response auto-extraction

record(resp) and the function wrapper recognise the two prevailing response shapes without naming any provider, best-effort and never throwing:

  1. { model, usage: { prompt_tokens, completion_tokens, total_tokens }, choices: [{ finish_reason, message: { content, tool_calls: [{ function: { name, arguments } }] } }] }
  2. { model, usage: { input_tokens, output_tokens }, stop_reason, content: [{ text }] }

Both objects and plain dicts are handled.

Environment variables

| Variable | Purpose | Default | | ----------------------------- | --------------------------------------------------------------- | ---------------- | | TRACER_WATCH_DIR | Directory for local JSONL files. | .tracer/watch | | TRACER_CLOUD_KEY | Key that enables free Tracer Cloud streaming. | (unset) | | TRACER_CLOUD_URL | Base URL for the cloud sink. | provider default | | TRACER_WATCH_OTLP_ENDPOINT | Endpoint for the OTLP/HTTP sink. | (unset) | | TRACER_WATCH_OTLP_HEADERS | Comma-separated k=v headers for the OTLP sink. | (unset) | | TRACER_WATCH_DEBUG | Print why a telemetry send was dropped (never affects the host).| (unset) |

License

Apache-2.0