---
title: Claude Code Integration
description: Wire up agent-receipts-hook as a PostToolUse hook in Claude Code to capture native tool calls.
---

Claude Code fires `PostToolUse` hooks after every tool call — including native host tools that never go through an MCP server. Wiring up `agent-receipts-hook` as a PostToolUse hook ensures those calls appear in the daemon receipt chain alongside MCP tool calls captured by `mcp-proxy`.

## Prerequisites

- [agent-receipts-hook installed](/hook/installation/) and on `$PATH`
- `agent-receipts-daemon` running (see [Daemon Setup](/getting-started/daemon-setup/))

## Wire up the hook

Add the following to your `~/.claude/settings.json` (user-global, all projects) or to `.claude/settings.json` in a specific project:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "",
        "hooks": [{ "type": "command", "command": "agent-receipts-hook" }]
      }
    ]
  }
}
```

The empty `matcher` string covers all tools. Claude Code spawns `agent-receipts-hook` with a JSON frame on stdin after each tool call completes.

:::note[Absolute path]
If `agent-receipts-hook` is not on the `$PATH` Claude Code uses when launching hooks, replace `"agent-receipts-hook"` with the absolute path from `which agent-receipts-hook`. Claude Code hooks inherit a limited environment.
:::

:::tip[User-global vs project-level]
Add to `~/.claude/settings.json` to capture tool calls across all projects. Use `.claude/settings.json` in a project to limit capture to that project only.
:::

## Verify receipts appear

After running any Claude Code tool (e.g. a `Bash` command), check the dashboard — receipts with `channel: claude-code` should appear alongside any MCP receipts from `mcp-proxy`.

:::note
`agent-receipts list` is not yet implemented ([#410](https://github.com/agent-receipts/ar/issues/410)). Use the dashboard to inspect receipts in the interim.
:::

## What Claude Code sends

Claude Code serialises each PostToolUse event as a JSON object on stdin:

```json
{
  "hook_event_name": "PostToolUse",
  "session_id": "<current session ID>",
  "tool_name": "Bash",
  "tool_input": { "command": "go test ./..." },
  "tool_response": { "output": "PASS", "exit_code": 0 }
}
```

`agent-receipts-hook` maps this to:

| Receipt field | Source |
|---|---|
| `channel` | Fixed: `"claude-code"` |
| `tool.name` | `tool_name` from stdin |
| `tool.server` | Empty (native tools have no server) |
| `input` | `tool_input` as raw JSON |
| `output` | `tool_response` as raw JSON |
| `decision` | Fixed: `"allowed"` (PostToolUse fires after the tool ran) |
| `session_id` | `session_id` from stdin |

## MCP tool overlap

The empty matcher captures `mcp__*` tools too, which `mcp-proxy` already covers. This produces a second receipt per MCP call — one at `channel: "mcp"` from the proxy, one at `channel: "claude-code"` from the hook. They are distinguishable by their `channel` field. If you want to exclude MCP tools from the hook, add a non-empty matcher or restrict the hook to specific tool names. See the [overview](/hook/overview/#mcp-tool-overlap) for more detail.

## Session correlation

Claude Code passes the same `session_id` across all tool calls in a session. Both the hook and `mcp-proxy` forward this ID to the daemon, so all receipts from a given session are grouped together regardless of which channel they came from.

## Flags

| Flag | Description |
|---|---|
| `--format` | Force a specific input format. Defaults to auto-detection via `hook_event_name` in the stdin payload or the `CLAUDE_SESSION_ID` environment variable. Currently supported: `claude-code`. |

The `--format` flag is intended for testing and future runtime support. In normal Claude Code usage, auto-detection is sufficient.
