[BUG] Claude Code creates Honeycomb boards on startup using OTEL credentials
Summary
On startup, when OpenTelemetry is enabled via enterprise/managed settings, Claude Code appears to use the configured OTEL credentials (OTEL_EXPORTER_OTLP_HEADERS containing the Honeycomb API key) to call Honeycomb's Boards API and create dashboards/boards in the org's Honeycomb environment.
This is unexpected: the OTEL spec only defines signal export (metrics/logs/traces). Creating boards is a Honeycomb-specific control-plane action that should not be triggered by an OTLP exporter. Orgs end up with auto-generated boards they didn't ask for and have to clean up manually.
Reproduction
- Set up Claude Code under an enterprise/managed configuration with:
CLAUDE_CODE_ENABLE_TELEMETRY=1OTEL_EXPORTER_OTLP_ENDPOINTpointing at Honeycomb (e.g.https://api.honeycomb.io)OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=<API_KEY>where the key has board write scope (typical for ingest+config keys used in CI/managed envs)
- Launch Claude Code (any session that initializes telemetry).
- Check the Honeycomb environment's Boards list. New Claude-Code-related boards appear without being requested.
Expected
Claude Code's OTEL integration should only export signals via OTLP. It should not call the Honeycomb Boards API (or any backend control-plane API) to create dashboards.
Proposed shape of the fix
The fix does not have to be a single global flag. Either of these works, in order of preference:
- Don't reach into the backend control plane at all from OTEL setup. OTLP headers are for signal export only. If pre-built boards are useful, ship them as a separate, explicit provisioning step (e.g.
claude honeycomb install-boards) that the user invokes intentionally. - Enterprise-level credential separation. When OTEL is configured via enterprise/managed settings, expose a boolean (something like
honeycomb.allowControlPlaneWrites: falseby default) that prevents Claude Code from usingOTEL_EXPORTER_OTLP_HEADERSfor anything other than signal export. If provisioning is desired, it should read a separate, explicitly scoped credential from managed settings or a repo-level config, never from the OTLP headers. Telemetry auth should not imply provisioning auth. - Opt-in env flag (e.g.
CLAUDE_CODE_HONEYCOMB_INSTALL_BOARDS=1), default off, idempotent (detect existing boards and skip), documented in the monitoring page.
Whichever shape lands, the guarantee should be: launching the CLI does not mutate third-party SaaS state without an explicit, separately-credentialed user action.
Why this matters
- Enterprise orgs treat their Honeycomb workspace as managed infra. Surprise board creation by a CLI is noise at best, and at worst pollutes a curated workspace.
- The only current workaround is to fully disable telemetry (
CLAUDE_CODE_ENABLE_TELEMETRY=0), which loses the actual telemetry value. - Scoping the OTLP headers down to ingest-only on the Honeycomb side mitigates this, but most managed deployments use a broader-scope key by default, which is why credential separation needs to live on the Claude Code side too.
Environment
- Claude Code: enterprise managed install (latest)
- OTEL backend: Honeycomb (only. Datadog and others do not exhibit this since the behavior is Honeycomb-API specific)
- Telemetry enabled via org-wide managed settings
Related
- #42281 (Native OTLP Trace/Span Export)
- #53075 (Analytics docs should clarify telemetry opt-out effects)
- #46204 (3P OpenTelemetry on enterprise/managed accounts)
9 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
This is observability-side-effect leakage at the startup credential boundary.
If Claude Code creates Honeycomb boards on startup using OTEL credentials, then telemetry credentials intended for observation are being treated as sufficient authority for a write-side product action during initialization.
Why it matters:
I would want clarity on:
Startup integrations need least-surprise side-effect semantics. If OTEL credentials are enough for Claude Code to create Honeycomb boards on launch, the credential boundary is broader than users can safely assume.
@0xbrainkid agreed, "observability-side-effect leakage at the startup credential boundary" nails it.
Concrete asks on top of your three points:
honeycomb.allowControlPlaneWrites: falseby default) that prevents Claude Code from usingOTEL_EXPORTER_OTLP_HEADERSfor anything other than signal export. If provisioning is actually desired, it should read a separate, explicitly scoped credential from managed settings or a repo-level config, never from the OTLP headers. Telemetry auth should not imply provisioning auth.Least-surprise at startup is the right bar. Launching the CLI should not mutate third-party SaaS state without an explicit, separately-credentialed user action. I updated the issue body to fold this in.
I think the underlying issue is a bit different than what was described and its solution is simpler.
To send OTEL data from claude to track usage, the docs say you need to change the environment variables.
https://code.claude.com/docs/en/monitoring-usage#quick-start
For it to be an organization-wide setting you need to update settings.json in the organization settings owner's console
In that settings.json, you need to set the standard OTEL environment variables.
i.e.:
CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_EXPORTER_OTLP_ENDPOINT=...
OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=some_secret
OTEL_EXPORTER_OTLP_PROTOCOL=...
OTEL_LOGS_EXPORTER=...
OTEL_METRICS_EXPORTER=...
The issue itself is that a terminal that's using claude with these settings directly (and processes spawned from such claude session) inherits those environment variables. Thus if I start my own service, e.g.:
npm run startusing claude, it will have those OTEL environment variables. For honeycomb's case, it can use those variables to create new datasets and push data to a collector that is supposed to be used only for claude tracking purposes.In my local environment I would expect to have my own OTEL collector via docker compose, so instead of sending my traces/spans/logs/metrics to that collector, im sending them to the one that my team defined (for this case, honeycomb).
A solution would be rather simple, have Claude use the same environment variables, but with prefix CLAUDE, so CLAUDE_OTEL_EXPORTER_OTLP_ENDPOINT, ... etcetera.
This way if they are inherited, they won't override in any way the regular OTEL environment variables one would expect.
@bcherny does this sound reasonable?
Landed a change to strip out the env vars to avoid this from happening.
Thanks for the quick work @mhegazy. In which version do you think this will ship? sorry for the insistence
Should be in v2.1.129
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.