Claude Code
Three ways to connect Claude Code, and they combine:
- The importer records whole sessions from the transcripts Claude Code already writes — every model call, tool call and sub-agent — with no setup. Start there: Claude Code and Codex.
- The hook pack, below, puts a run fuse and nudges in front of every tool call.
- Claude Code’s own OpenTelemetry export (beta), below, adds its spans to the timeline.
A run fuse and nudges on every tool call
The engine’s
Claude Code hook pack
makes each Claude Code session a Traza run: its session_id is the run id.
As a PreToolUse hook it asks the pre-call check before each tool call,
naming the tool, and acts on the answer:
| Traza says | Claude Code does |
|---|---|
continue or warn, no nudges |
the call goes through its normal permission flow |
an advice nudge |
the nudge is added as context next to the tool result |
a block nudge, or stop |
the call is refused, with the reason shown to Claude |
It never answers “allow”, so your own permission prompts still ask what they would have asked. A SessionStart hook adds up to three earlier runs from the same project as context, inside a block marked untrusted.
It needs Python 3.8 or later and nothing else. From a checkout of the open engine, in your project:
python3 examples/claude-code/install.py --url https://api.trazadb.com
export TRAZA_TOKEN=tzk_… # a read key, in the environment Claude Code runs in
The installer copies the hook into .claude/hooks/traza/ and merges its
entries into .claude/settings.json, keeping every other setting; --user
installs for every project, --uninstall removes it. The token never goes
into either file. If Traza cannot be reached the hook lets the call through;
--fail-closed refuses it instead.
The hook pack does not record the session. Run the importer with --watch
beside it, so the fuse has steps to count and Mission Control shows the
session live; see Claude Code and Codex. Then give the
sessions a policy that stops a looping one, with a full key:
curl -s https://api.trazadb.com/v1/fuses/policies \
-H "Authorization: Bearer $TRAZA_FULL_KEY" \
-d '{"name": "claude-code", "match": {"service": "claude-code"},
"limits": {"max_repeats": 5, "max_steps": 400}, "action": "stop"}'
A stopped session stays stopped until someone resets it: from Mission Control,
a push notification, a Slack alert, or POST /v1/fuses/runs/<session id>/reset.
Nudge it from the same places; see Steer.
Claude Code’s own traces (beta)
Claude Code can export OpenTelemetry spans itself. Tracing is a beta feature there and is off by default:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1
export OTEL_TRACES_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.trazadb.com
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20$TRAZA_API_KEY"
Traza stores every span Claude Code sends. Claude Code names its attributes
its own way (model, input_tokens, tool_name), not with the GenAI keys
Traza’s token rollups and step detection read, so model, token and tool
fields from these spans do not populate Traza’s analytics or count as tool
steps for Guard. Use the importer for runs, the hook for guarding, and these
spans for the timeline. Claude Code redacts prompts and tool details from its
spans unless you set its OTEL_LOG_* variables; see its monitoring
documentation.