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

autotel-claude-code

v0.1.1

Published

OpenTelemetry for Claude Code plugins (a Claude Mod): $.autotel spans for plugin authors, one span per hook dispatch with the chain beneath it, and each tool call's duration on its row

Readme

autotel-claude-code

OpenTelemetry for Claude Code plugins, as a Claude Mod.

Function hooks make every plugin a middleware chain: each $ call is an event, hooks nest by registration order, and a hook may answer for the tool beneath it. Claude Code's own OTel export tells you what the model and the tools did; this mod tells you what the hooks did around them — which plugin sat where, how long each link took, and who said no.

What it records

  • One trace per interaction. A claude_code.turn root opens at prompt.submit and closes at turn.complete, carrying the turn id, its reason and duration.
  • One span per dispatch worth the bytes — tool.call, tool.check, turn.step (each model call), every classic.* shell hook, process.run, http.fetch, fs.read/fs.write, mcp.call, model.*, agent.spawn, command.run. Getters, per-draw and per-tick events are left out.
  • The chain beneath, one span event per link: plugin.name, tier, outcome (returned, passed, skipped, expired, …), own wall time, and the skip reason. A denied dispatch names the plugin that decided it in claude_code.decided_by: the final denial, followed down through the links that passed it along unchanged.
  • The call's duration on its row. A ToolUse render hook appends 1.2s — or denied by hook · 3ms — beside the tool row in the terminal and the desktop app.

Every span is INTERNAL, attributed with claude_code.event, plugin.name (who raised it) and claude_code.tier; a tool.call adds tool_name, tool_use_id and agent_id in a subagent.

$.autotel for plugin authors

The mod adds one noun in the engine.create fold:

const summary = await $.autotel.span(
  'summarise',
  async (span) => {
    span.setAttribute('gen_ai.request.model', model);
    return $.model.complete(request);
  },
  { 'plugin.feature': 'summary' },
);

The span joins the current turn's trace beside the dispatches above. It ends when the body settles; a throw marks it failed with the error's message and rethrows. Types come from this package: add node_modules/autotel-claude-code/types to your tsconfig include, or import type { Autotel } from 'autotel-claude-code', and EngineInterface gains autotel.

Where the mod is not seated, $.autotel is absent and the call throws — the same contract as Claude Code's built-in $.telemetry.

Install

Function hooks ship behind a flag while Anthropic finishes them:

npm install autotel-claude-code
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude --plugin-dir node_modules/autotel-claude-code

Or point a marketplace at the package directory. The mod exports to whatever OTEL_EXPORTER_OTLP_ENDPOINT names, over OTLP/HTTP JSON, honouring OTEL_EXPORTER_OTLP_HEADERS and OTEL_SERVICE_NAME (default claude-code, so the spans sit beside Claude Code's own). With no endpoint set it records nothing and $.autotel.span only runs its body.

autotel-devtools claude sets the endpoint for you:

CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 npx autotel-devtools claude --plugin-dir node_modules/autotel-claude-code

How it is built

The plugin runs inside Claude Code's hook sandbox (a Bun worker, no ambient imports), so there is no OpenTelemetry SDK here: spans are plain records batched over $.clock.after and posted with $.http.fetch. hooks/register.ts is the boundary that reads the engine's e and next into plain values; hooks/recorder.ts decides what a span is named, where it sits and what it carries; hooks/otlp.ts encodes and sends. The hooks are type-checked against the declarations /plugin-types writes, vendored in types/claude-code.d.ts.

claude plugin validate . lists the hooks, the $ calls and the environment variables the module reads — nothing else is reachable.

Limits

  • A dispatch's own $ calls (a hook reading a file during tool.call) are siblings under the turn, not children of the dispatch: the sandbox has no async context to carry a parent across.
  • One attempt per batch; a collector that is down loses that batch. Devtools is loopback, so this has not mattered yet.