Monitor Claude Code with TraceHawk
Claude Code is Anthropic's agentic coding tool — it uses dozens of MCP servers and tool calls per session. TraceHawk gives you full visibility: every tool invocation, every MCP server call, token cost per session, and a timeline of what the agent decided to do and why.
Install
pip install tracehawkOption 1 — Claude Code hooks (recommended)
Claude Code supports lifecycle hooks in .claude/hooks/. This is the cleanest integration — zero changes to your prompts or workflow.
# .claude/hooks/pre_tool_call.py
"""
TraceHawk hook — traces every tool call Claude Code makes.
Place in your project's .claude/hooks/ directory.
"""
import tracehawk
import json, sys, time
tracehawk.init(api_key="ao-...")
def on_pre_tool_call(event: dict) -> dict:
"""Called before each tool invocation."""
# event contains: tool_name, tool_input, conversation_id
event["_th_start"] = time.time()
return event
def on_post_tool_call(event: dict) -> dict:
"""Called after each tool invocation with result."""
duration_ms = (time.time() - event.get("_th_start", time.time())) * 1000
tracehawk.trace_tool_call(
tool_name=event.get("tool_name"),
tool_input=event.get("tool_input", {}),
tool_result=event.get("tool_result", {}),
duration_ms=duration_ms,
conversation_id=event.get("conversation_id"),
error=event.get("error"),
)
return eventRegister the hook
Add to your .claude/settings.json:
{
"hooks": {
"pre_tool_call": ".claude/hooks/pre_tool_call.py::on_pre_tool_call",
"post_tool_call": ".claude/hooks/pre_tool_call.py::on_post_tool_call"
}
}Option 2 — Python SDK decorator
If you drive Claude Code programmatically (CI, scripts, multi-agent pipelines), wrap your entry point with @tracehawk.observe. The decorator creates a parent trace — all tool calls inside become child spans.
"""
Alternative: use the Python SDK directly in your agent script.
Works when you control the script that spawns Claude Code programmatically.
"""
import tracehawk
import subprocess
tracehawk.init(api_key="ao-...")
@tracehawk.observe(name="claude-code-session")
def run_agent_task(prompt: str, project_dir: str) -> str:
"""Run a Claude Code task and trace it end-to-end."""
result = subprocess.run(
["claude", "--print", prompt],
cwd=project_dir,
capture_output=True,
text=True,
)
return result.stdout
# Run — full session appears as one trace in TraceHawk
output = run_agent_task(
prompt="Add unit tests for the authentication module",
project_dir="/path/to/project"
)Option 3 — MCP observer server
Add @tracehawk/mcp-observer as an MCP server in your Claude Code config. It acts as a transparent middleware — intercepts every tool call to every other MCP server and forwards telemetry to TraceHawk. No code changes. Works in Claude Desktop too.
# .claude/settings.json — enable TraceHawk MCP server
{
"mcpServers": {
"tracehawk": {
"command": "npx",
"args": ["-y", "@tracehawk/mcp-observer"],
"env": {
"TRACEHAWK_API_KEY": "ao-..."
}
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "ghp_..." }
}
}
}What a captured MCP span looks like
Every MCP tool call is stored with full context — server, tool, input, duration, and status. These feed into the MCP Analytics dashboard automatically.
# Every MCP tool call captured as a span:
{
"span_kind": "MCP",
"mcp.server_name": "filesystem",
"mcp.tool_name": "read_file",
"mcp.tool_input": { "path": "/workspace/src/auth.ts" },
"duration_ms": 12,
"status": "ok"
}What you see in TraceHawk
- ✓Full session timeline — every tool call in order with durations
- ✓MCP server breakdown: filesystem vs GitHub vs Slack vs your custom servers
- ✓Token cost per session: which prompts cost the most
- ✓Error visibility: failed tool calls with full error message
- ✓Decision tree: read_file → edit_file → run_tests chain visible as parent-child spans
- ✓Per-project cost trends: compare sessions across branches or PRs
Frequently asked questions
Does this work with Claude Desktop?
Yes. Option 3 (MCP observer server) works in any MCP-compatible host — Claude Desktop, Claude Code, or custom agent harnesses. Add it to your MCP server list and all tool calls through that host are traced.
Does TraceHawk see my code or file contents?
By default, TraceHawk captures tool names, parameter keys, and metadata — not file contents. PII redaction is on by default. You can configure full payload capture for internal tools where you need complete observability.
How do I trace multi-agent sessions where Claude Code calls another agent?
Pass the trace_id from the parent session as a header or environment variable into the child agent. TraceHawk will stitch the spans into a single trace tree automatically.
Ready to ship?
Free tier — 50K spans/month. No credit card required.