Claude Code Observability: Track Every Tool Call, Token and Cost (2026)
See every prompt, tool call, token and dollar of your Claude Code sessions in one timeline, with one command and your privacy level.
On this page
Claude Code reads files, runs shell commands, edits code and calls MCP tools on your behalf, sometimes for an hour at a time. When a session goes well you rarely ask what it did. When it goes badly (a surprising bill, a command you did not expect, a session that hangs) you need the full record: every prompt, every tool call, how long each one took and what it cost.
This guide shows what Claude Code exposes, how to capture it yourself, and how to get a complete timeline with one command.
Why observe Claude Code at all
- Cost. Long sessions with big contexts add up, and cache reads and writes change the bill a lot. You want cost per session and per task, not just a monthly total.
- What actually ran. Every
Bashcommand, every file edit, every MCP call. Useful for reviews, for audits and for learning what the agent does well. - Why it got stuck. A tool call that started and never finished, a loop of failed edits, a compaction in the middle of a task.
- Team visibility. When several people use Claude Code, a shared view answers "who is spending what, on which repo" without asking around.
What Claude Code exposes
Claude Code gives you two hooks into a session:
- Hooks. Shell commands that run on lifecycle events and receive a JSON payload. The useful ones for observability are
UserPromptSubmit(a new prompt),PreToolUseandPostToolUse(before and after each tool call),StopandSubagentStop(a response or subagent finished),NotificationandPreCompact(the context is about to be compacted). Hooks live in~/.claude/settings.jsonor in a project's.claude/settings.json. - OpenTelemetry. Claude Code can also export metrics and events over OpenTelemetry when telemetry is enabled, which suits teams that already run a collector.
Every hook payload carries a session_id, so all events of one Claude Code launch can be grouped together.
Option 1: wire it yourself
The minimal do-it-yourself setup is a hook that appends each payload to a file:
{
"hooks": {
"PostToolUse": [
{ "hooks": [{ "type": "command", "command": "cat >> ~/claude-tool-calls.jsonl" }] }
]
}
}
It works, and it is a good way to see the raw data. The limits show up quickly: you have to pair each PreToolUse with its PostToolUse to get durations, compute cost from token counts and per-model prices, scrub secrets from prompts and command output before they land anywhere shared, and build the views yourself. The OpenTelemetry route solves transport, not the views: you still need a backend and dashboards.
Option 2: Voight in one command
Voight is an observability and debugging platform for AI agents, and Claude Code is a first-class source. One command sets it up:
npx -y @voightxyz/sdk setup
The wizard detects Claude Code (it also supports Cursor and Codex), asks for your privacy level and your Voight API key, and writes two things into ~/.claude/settings.json:
env.VOIGHT_KEYandenv.VOIGHT_PRIVACY, so the key never lives in your shell profile.- Hooks on
UserPromptSubmit,PreToolUse,PostToolUse,Stop,SubagentStop,NotificationandPreCompact, each callingnpx -y @voightxyz/sdk hook.
Restart Claude Code (hooks are read on startup) and the next session appears in the dashboard within seconds.
Choose a privacy level
| Level | What leaves your machine |
|---|---|
| Minimal | Metadata only: tool names, timings, tokens, cost. No prompts, responses, file paths or git context. |
| Standard (recommended) | Full content, with credentials and personal data scrubbed locally before sending. |
| Full | Everything as captured. |
You can change the level later by running setup again, for example npx -y @voightxyz/sdk setup --privacy=standard.
Running setup from a script or another agent
If the terminal is not interactive (CI, or an agent running the command for you), setup works in three explicit steps:
npx -y @voightxyz/sdk setup
npx -y @voightxyz/sdk setup --privacy=2
npx -y @voightxyz/sdk setup --privacy=2 --key=vk_YOUR_KEY
What you see
- Sessions. One per Claude Code launch, grouped by day.
- Traces. All the work for one ask, inside its session.
- Tool calls as single rows. Each
PreToolUseis paired with itsPostToolUse, so every call shows its duration and outcome. A call that starts and gets no result for more than two minutes is flagged, which is how hung commands surface. - Tokens and cost on every event, with model tags and cache reads and writes counted separately.
- A privacy chip on each event (MIN, STD or FULL), so you can confirm what was captured.
- Issues and AI diagnosis. Failed runs are grouped into issues, and one click returns a root cause and a suggested fix you can hand back to Claude Code.
Questions you can answer in a minute
| Question | Where to look |
|---|---|
| Why did yesterday cost so much? | Cost per session, then per trace inside it |
| What commands did it run on this repo? | The tool calls of the session, filtered by Bash |
| Why did the session hang? | The flagged call that started and never finished |
| Did it touch anything sensitive? | The audit log, with the privacy level of each event |
| Which tasks fail most often? | The issue queue, ordered by frequency |
Troubleshooting
- No events in the dashboard. Check that
~/.claude/settings.jsonhasenv.VOIGHT_KEYand hooks callingnpx -y @voightxyz/sdk hook, then restart Claude Code. - npx runs an old version. Run
npx -y @voightxyz/sdk@latest --version, or clear the cache withrm -rf ~/.npm/_npx. - Prompts are not captured. You are on Minimal, which drops content by design. Run setup again with Standard.