PythonMCP-nativeNew

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 tracehawk

Option 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
# .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 event

Register the hook

Add to your .claude/settings.json:

.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.

run_agent.py
"""
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
# .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.

Get started free →