OTEL env vars from settings.json leak into Bash tool subprocesses
Problem
When OTEL environment variables are configured in settings.json (or managed settings), they are inherited by all child processes spawned by the Bash tool. This causes user applications to inadvertently initialize OpenTelemetry exporters and attempt to connect to localhost:4317.
Reproduction
- Configure OTEL telemetry in
~/.claude/settings.json:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp"
}
}
- Ask Claude to run any application that uses an OTel-aware framework (Java Spring, Python Flask, Go, Node.js):
run: go test ./...
run: npm test
run: python main.py
- The user's application sees
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317in its environment and auto-initializes an OTLP exporter, causing:
- Connection errors if no collector is running on
:4317 - Telemetry pollution if a collector IS running (user app telemetry mixed with Claude Code telemetry)
Impact
This is especially problematic for enterprise deployments where OTEL settings are pushed via managed settings (macOS managed preferences). Users cannot remove the variables themselves, and every Bash tool invocation leaks the OTEL config into their applications.
Many OTel SDKs (Java, Python, Go, Node.js) auto-configure when they detect OTEL_EXPORTER_OTLP_ENDPOINT — no code changes needed. This makes the env var leakage silently break or pollute user applications.
Proposed Solution
Claude Code should **not propagate its own OTEL_ env vars* to child processes spawned by the Bash tool. These variables are meant to configure Claude Code's internal telemetry, not user applications.
Options (in order of preference):
- **Strip OTEL_ vars from Bash tool subprocess environment* — Claude Code reads the OTEL config at startup; child processes don't need them. This is the simplest and most correct fix.
- Support
env.excludepatterns in settings — Allow settings like:
{
"env": {
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4317"
},
"envExcludeFromSubprocesses": [
"OTEL_*",
"CLAUDE_CODE_ENABLE_TELEMETRY"
]
}
- Support file-based OTel config — Instead of env vars, allow OTEL to be configured via a dedicated settings key that doesn't touch the environment at all:
{
"telemetry": {
"endpoint": "http://localhost:4317",
"protocol": "grpc",
"metricsExporter": "otlp"
}
}
Workaround Attempted
We tried using a SessionStart hook with CLAUDE_ENV_FILE to unset the OTEL vars, but could not get hooks to fire (separate issue).
Related
- #7099 — Feature request for granular shell environment policy (auto-closed, same root cause)
- Claude Code monitoring docs — documents the OTEL env var configuration
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗