Docs menu

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.