[FEATURE] - [Telemetry] Opt-in for verbatim plugin/skill labels on token.usage and cost.usage metrics

Open 💬 3 comments Opened May 17, 2026 by maorzilberg

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

We operate an internal Claude Code marketplace (~10 plugins, growing) and run a local OpenTelemetry → Prometheus → Grafana stack so plugin authors can see token usage, cache-hit ratio, and cost-per-invocation broken down by which plugin consumed the tokens.

That breakdown is the central question the framework exists to answer ("which of my plugins is expensive?"), and right now it's impossible to answer.

When a skill from a non-Anthropic plugin is invoked, Claude Code emits claude_code.token.usage and claude_code.cost.usage metrics with plugin_name="third-party" and skill_name="third-party" - regardless of OTEL_LOG_TOOL_DETAILS=1 or any other knob we could find in the docs. Every plugin in our marketplace lumps into a single "third-party" bucket on those metrics.

The redaction is also asymmetric:

  • claude_code.skill_activated events emit verbatim plugin/skill names.
  • agent_name on token.usage is verbatim (e.g. "Explore" when a subagent fires inside a third-party plugin's context).
  • Only plugin_name and skill_name on token/cost metrics are redacted.

So Claude Code clearly has the verbatim names at the moment those metrics are emitted - they just get scrubbed before export

Proposed Solution

Either of the following would solve our problem; they're listed in order of our preference.

Option A - opt-in env var. Add OTEL_LOG_PLUGIN_DETAILS=1, paralleling the existing OTEL_LOG_TOOL_DETAILS=1 and OTEL_LOG_USER_PROMPTS=1 opt-ins. When set, emit verbatim plugin_name and skill_name on claude_code.token.usage, claude_code.cost.usage, and claude_code.code_edit_tool.decision.
Default stays redacted - the operator explicitly chooses to surface this to their own collector.

Interaction:
``bash
export OTEL_LOG_PLUGIN_DETAILS=1
claude
``
# now: claude_code_token_usage_tokens_total{plugin_name="jira-to-plan", skill_name="ticket-fetcher", ...}

Option B - trust allowlist. Support trustedPluginSources: [...] in settings or a CLAUDE_TRUSTED_PLUGIN_SOURCES env var listing marketplace URLs / plugin namespaces whose names should not be redacted.
Plugins matching the list emit verbatim labels; everything else stays redacted.
Narrower privacy surface than the global env var, and it mirrors the trust model Claude Code already uses for plugin auto-install gating.

Alternative Solutions

We tried each of these before filing this issue.

  1. OTEL_LOG_TOOL_DETAILS=1 - only affects tool input logging, not metric labels. No effect on the third-party redaction.
  2. Per-plugin shell wrappers that prepend plugin.name=X to OTEL_RESOURCE_ATTRIBUTES before invoking claude - works for one-shot CI runs, but doesn't help interactive sessions where users invoke multiple plugins.
  3. session_id correlation -pure session-id joins fail for multi-plugin sessions (which plugin owns the tokens when two plugins fire in one session?).
  4. A PreToolUse hook on the Skill tool that emits its own attribution event -this is what we ended up shipping as a workaround. It POSTs an OTLP log to the local collector with verbatim plugin.name / skill.name

/ session.id on every Skill invocation, and the dashboard does a PromQL join with token_usage time-bucketed by session_id.

  1. This works, but:
  • It duplicates information Claude Code already has internally.
  • Hooks only see the tool boundary, so attribution is approximate - we can't bind tokens consumed during a multi-turn skill execution back to that skill with certainty.
  • The time-bucketed PromQL join is fragile at activation boundaries (back-to-back plugin invocations within one batch interval get misattributed).
  • Every new marketplace operator who wants per-plugin cost has to install this hook plugin, when the data already exists upstream.

Priority

Medium - Would be very helpful

Feature Category

Other

Use Case Example

Scenario: a marketplace operator (us) running a Tuesday cost review.

  1. Author of an internal jira-to-plan plugin asks: "did my refactor last week reduce token usage?"
  2. Operator opens the marketplace dashboard, filters last 7 days, sorts by sum(rate(claude_code_cost_usage_USD_total[7d])) by (plugin_name).
  3. With current redaction: dashboard shows two rows - plugin_name="third-party" with $42 spent across the org, and a smattering of Anthropic builtin subagents. The author cannot tell whether jira-to-plan got

cheaper, more expensive, or unchanged. The dashboard is unanswerable for its primary use case.

  1. With OTEL_LOG_PLUGIN_DETAILS=1 (Option A): dashboard shows one row per Driivz plugin. Author sees jira-to-plan dropped from $8.20 → $5.10 week-over-week, confirms the refactor worked, ships it more widely.

Same scenario applies to: finding expensive skills inside cheap plugins, comparing model selection across plugins (Opus-heavy vs. Haiku-heavy), and showing a plugin author "your cache-read ratio is 30% - fix your
prompt caching."

Additional Context

_No response_

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗