Claude Code
Claude Code can export its sessions over OpenTelemetry. Send them to Packrat, and the analyst knows why a change was made: when it checks a deploy, it reads what was asked in the sessions that made the deploy's commits, and what those sessions ran in production after the commit.
This is a setting in Claude Code. Nothing is installed in your app.
Prerequisites
-
Sign up for Packrat. It's free.
-
Copy your ingest key from the setup page. It starts with
packrat_ingest_. -
Install the Packrat CLI and sign in, so you can check what Packrat receives:
curl -fsSL https://packrat.sh/cli | sh packrat login
The analyst matches a session to a commit by repository, so connect your app's GitHub repository on the app's Analyst page.
What Packrat gets
Claude Code sends logs, metrics and traces for each session:
- The prompts you type
- Each tool call, with the command for a Bash call
- Token counts, cost and time for each request to the model
- The repository the session ran in
Prompts and commands can hold anything you type, a secret included. To send only counts, leave out
OTEL_LOG_USER_PROMPTS and OTEL_LOG_TOOL_DETAILS. The analyst then cannot match a session to a
commit, because it finds the commit by the git commit command the session ran.
Send every session
Claude Code reads the exporter settings only from your user settings. In a project's
.claude/settings.json it ignores them and says so only under claude --debug.
Add this to ~/.claude/settings.json:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_TRACES_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_EXPORTER_OTLP_ENDPOINT": "https://ingest.packrat.sh",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer <your ingest key>",
"OTEL_SERVICE_NAME": "claude-code",
"OTEL_RESOURCE_ATTRIBUTES": "deployment.environment.name=development",
"OTEL_METRICS_INCLUDE_REPOSITORY": "true",
"OTEL_LOG_USER_PROMPTS": "1",
"OTEL_LOG_TOOL_DETAILS": "1"
}
}
Keep OTEL_SERVICE_NAME as claude-code: the analyst looks for sessions in the org's claude-code
apps. The protocol must be http/protobuf; Packrat does not take OTLP as JSON.
Every session on this machine now goes to one org, whatever repository it runs in.
Send only some repositories
If you work on repositories that belong to someone else, give the key to each repository instead.
Keep everything above in ~/.claude/settings.json except OTEL_EXPORTER_OTLP_HEADERS. A session
with no key is refused, so Packrat keeps nothing from it.
In each repository that should report, add a script that prints the header, and name it in the
project's .claude/settings.json. The script reads the key from the environment or from the
repository's git-ignored .env, so the key is never committed:
#!/bin/sh
# bin/claude-otel-headers
cd "$(dirname "$0")/.." || exit 1
key=${PACKRAT_INGEST_KEY:-$(sed -n 's/^PACKRAT_INGEST_KEY=//p' .env 2>/dev/null | tail -1)}
if [ -n "$key" ]; then printf '{"Authorization":"Bearer %s"}\n' "$key"; else echo '{}'; fi
{
"otelHeadersHelper": "bin/claude-otel-headers"
}
Make the script executable with chmod +x bin/claude-otel-headers.
Check it works
Start a new Claude Code session, ask it one thing, and quit. After a minute, ask Packrat what it receives from claude-code/development:
packrat status --app claude-code/development
Logs and metrics arrive first. A short session can send no traces.
Not seeing data?
- Nothing arrives: run
claude --debugand look for a warning that a setting was ignored. The exporter settings must be in~/.claude/settings.json, not in the project's settings. - Sessions arrive, but no deploy names them: check that the app's repository is connected, and
that
OTEL_METRICS_INCLUDE_REPOSITORYandOTEL_LOG_TOOL_DETAILSare set.