> ## Documentation Index
> Fetch the complete documentation index at: https://raindrop.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Code CLI (Beta)

> Automatic observability for Claude Code CLI sessions. Install once, then every session, tool call, and prompt is tracked in Raindrop.

The `@raindrop-ai/claude-code` package instruments
[Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code/overview) using its native
[hooks system](https://docs.anthropic.com/en/docs/claude-code/hooks). No wrapper or proxy
needed — your workflow stays exactly the same.

**What gets tracked:**

* Every prompt turn as a separate event, grouped by session
* Tool calls (Bash, Edit, Write, Read, etc.) with inputs, outputs, and real durations
* Token usage per turn and per session (input, output, cache read, cache creation)
* Model name and service tier
* CLAUDE.md and rules file contents (captured via `InstructionsLoaded`)
* `--append-system-prompt` and `--append-system-prompt-file` content (best-effort)
* Self-diagnostics — agent-reported issues (capability gaps, broken tools, etc.) via MCP tool, with [custom signal categories](#custom-self-diagnostics-signals)
* Subagent spawns and completions with duration
* Permission denials (tool calls blocked by auto-mode)
* Context compaction events
* Claude's final responses
* Errors and failures
* Nested trace view — tool calls appear under the root span, subagent tools nest under the subagent

## Installation

There are two ways to install: as a **Claude Code plugin** (recommended) or via **npm**.

### Option A: Plugin (recommended)

Install as a Claude Code plugin for clean enable/disable/uninstall without modifying `settings.json`:

```bash theme={null}
claude plugin marketplace add raindrop-ai/claude-code-plugin
claude plugin install raindrop
```

Set your write key via environment variable — no `setup` command needed:

```bash theme={null}
export RAINDROP_WRITE_KEY=your-write-key
```

Or add it to your project's `.claude/settings.json`:

```json theme={null}
{
  "env": {
    "RAINDROP_WRITE_KEY": "your-write-key"
  }
}
```

To disable, enable, or uninstall:

```bash theme={null}
claude plugin disable raindrop    # stop sending events
claude plugin enable raindrop     # resume sending events
claude plugin uninstall raindrop  # remove completely
```

### Option B: npm + setup

Install the package globally and run the setup command:

<CodeGroup>
  ```bash npm theme={null}
  npm install -g @raindrop-ai/claude-code
  ```

  ```bash pnpm theme={null}
  pnpm add -g @raindrop-ai/claude-code
  ```

  ```bash yarn theme={null}
  yarn global add @raindrop-ai/claude-code
  ```
</CodeGroup>

```bash theme={null}
raindrop-claude-code setup --write-key=YOUR_KEY --user-id=your-username
```

This saves your write key to `~/.config/raindrop/config.json` and adds hook entries to `~/.claude/settings.json`.

### Per-Project Setup

By default, hooks are installed globally (`~/.claude/settings.json`). To scope hooks to a single project instead, use `--scope=project` — this writes to `.claude/settings.json` in the current directory:

```bash theme={null}
raindrop-claude-code setup --scope=project
```

| Scope            | Settings file                  | Applies to        |
| ---------------- | ------------------------------ | ----------------- |
| `user` (default) | `~/.claude/settings.json`      | All projects      |
| `project`        | `.claude/settings.json` in cwd | This project only |

<Info>
  The setup merges hooks into your existing settings file — it won't overwrite your other hooks or settings.
</Info>

That's it. Start a Claude Code session and events will appear in your Raindrop dashboard.

***

## How It Works

Claude Code's [hooks system](https://docs.anthropic.com/en/docs/claude-code/hooks) fires shell commands
at lifecycle points (session start, prompt submit, tool use, etc.). The setup command registers
`raindrop-claude-code hook` as a synchronous command hook for each event type.

When a hook fires, Claude Code pipes a JSON payload to stdin. The handler parses it, maps it to
Raindrop's event and trace format, and POSTs to the Raindrop API.

Hooks are **synchronous by default** so they complete before Claude Code exits — this is essential for
headless/one-shot usage (`claude -p`). For interactive use cases where you prefer non-blocking hooks,
pass `--async` during setup:

```bash theme={null}
raindrop-claude-code setup --async
```

```
Claude Code CLI
  → fires hook (e.g. PostToolUse)
  → pipes JSON to raindrop-claude-code hook
  → maps to Raindrop event/trace format
  → POST to api.raindrop.ai
```

### Events Captured

| Claude Code Event    | What's Tracked                                                                        |
| -------------------- | ------------------------------------------------------------------------------------- |
| `SessionStart`       | Session metadata (model, working directory)                                           |
| `UserPromptSubmit`   | User's prompt text (each turn is a separate event)                                    |
| `PreToolUse`         | Tool start timestamp (used to compute duration)                                       |
| `PostToolUse`        | Tool call span with name, input, output, and duration                                 |
| `PostToolUseFailure` | Failed tool call span with error details                                              |
| `InstructionsLoaded` | CLAUDE.md and rules file contents                                                     |
| `SubagentStart`      | Subagent spawn with type and ID                                                       |
| `SubagentStop`       | Subagent completion with duration and result                                          |
| `PermissionDenied`   | Blocked tool call with denial reason                                                  |
| `PostCompact`        | Context compaction trigger and summary                                                |
| `Stop`               | Claude's response + token usage, model, tools from transcript + system prompt content |
| `StopFailure`        | Response with error information                                                       |
| `SessionEnd`         | Session end reason                                                                    |

All events within a session share the same `convoId` (derived from Claude Code's `session_id`),
so they appear grouped in the Raindrop dashboard.

<Info>
  Some events (`InstructionsLoaded`, `StopFailure`, `PostCompact`, `PermissionDenied`) require a minimum Claude Code version. Setup auto-detects your installed version and only registers supported hooks.
</Info>

### Enriched Properties at Stop

When a turn completes (`Stop` or `StopFailure`), the transcript JSONL file is parsed to extract data that hooks alone can't provide:

| Property                     | Description                                                                 |
| ---------------------------- | --------------------------------------------------------------------------- |
| `ai.usage.prompt_tokens`     | Input tokens for the current turn                                           |
| `ai.usage.completion_tokens` | Output tokens for the current turn                                          |
| `ai.usage.cache_read_tokens` | Prompt cache hits for the current turn                                      |
| `ai.usage.session_total.*`   | Cumulative token totals across the session                                  |
| `ai.model`                   | Model used (e.g. `claude-sonnet-4-6`)                                       |
| `ai.service_tier`            | API service tier                                                            |
| `ai.stop_reason`             | Why generation stopped (`end_turn`, `tool_use`, `max_tokens`)               |
| `ai.tools_used`              | Unique tools invoked (e.g. `Bash, Read, Write`)                             |
| `ai.turn_count`              | Number of API turns in the session                                          |
| `ai.duration_ms`             | Turn duration reported by Claude Code                                       |
| `ai.has_thinking`            | Whether extended thinking was used                                          |
| `claude_code.version`        | Claude Code CLI version                                                     |
| `git.branch`                 | Current git branch                                                          |
| `system_instructions`        | Contents of loaded CLAUDE.md and `.claude/rules/*.md` files                 |
| `append_system_prompt`       | Content from `--append-system-prompt` / `--append-system-prompt-file` flags |

A dedicated LLM span with `gen_ai.*` attributes is also created for backend token accounting.

<Info>
  `append_system_prompt` is captured best-effort by inspecting the parent process's command-line arguments. On Linux this is exact; on macOS positional args may be appended. If you use `--append-system-prompt-file`, the file contents are read directly.
</Info>

***

## Configuration

### Environment Variables

| Variable                    | Description                                                                                                  |
| --------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `RAINDROP_WRITE_KEY`        | API write key (overrides config file)                                                                        |
| `RAINDROP_USER_ID`          | User identifier (overrides config file, defaults to OS username)                                             |
| `RAINDROP_CONVO_ID`         | Override conversation ID (groups events across sessions)                                                     |
| `RAINDROP_PROJECT_ID`       | Route events to a specific [project](/platform/projects) (slug); omit for the default **Production** project |
| `RAINDROP_EVENT_NAME`       | Custom event name (default: `claude_code_session`)                                                           |
| `RAINDROP_PROPERTIES`       | JSON object merged into every event's properties                                                             |
| `RAINDROP_ENABLED`          | Set to `"false"` or `"0"` to disable all telemetry                                                           |
| `RAINDROP_API_URL`          | Custom API endpoint                                                                                          |
| `RAINDROP_LOCAL_DEBUGGER`   | Local debugger URL (auto-detected on `:5899` if not set)                                                     |
| `RAINDROP_DEBUG`            | Set to `"true"` for verbose logging                                                                          |
| `RAINDROP_SELF_DIAGNOSTICS` | JSON object to customize self-diagnostics signal categories                                                  |

### Custom Properties

To tag events with a product name, team, or any custom metadata, set `RAINDROP_PROPERTIES` as a JSON object:

```bash theme={null}
RAINDROP_EVENT_NAME=design-agent RAINDROP_PROPERTIES='{"product":"design","team":"ai"}' claude "do something"
```

For per-project tagging, add these to each project's `.claude/settings.json`:

```json theme={null}
{
  "env": {
    "RAINDROP_EVENT_NAME": "design-agent",
    "RAINDROP_PROPERTIES": "{\"product\":\"design\",\"team\":\"ai\"}"
  }
}
```

### Config File

The setup command creates `~/.config/raindrop/config.json`:

```json theme={null}
{
  "write_key": "your-write-key",
  "user_id": "your-username"
}
```

You can also set `event_name`, `custom_properties`, and `project_id` in this file:

```json theme={null}
{
  "write_key": "your-write-key",
  "user_id": "your-username",
  "event_name": "my-agent",
  "custom_properties": { "product": "my-product" },
  "project_id": "support-prod"
}
```

Precedence (low to high): config file → environment variables.

### Projects

If your org has multiple [projects](/platform/projects), route this agent's events to a specific one by setting its slug via `RAINDROP_PROJECT_ID` or the `project_id` config-file key:

```bash theme={null}
export RAINDROP_PROJECT_ID=support-prod
```

This sets the `X-Raindrop-Project-Id` header on every event. Omit it (or pass `default`) to use your org's default **Production** project, which is the existing behavior. Single-project orgs need nothing new.

### Custom Self-Diagnostics Signals

By default, the self-diagnostics MCP server exposes 5 signal categories (`missing_context`, `repeatedly_broken_tool`, `capability_gap`, `complete_task_failure`, `noteworthy`). You can replace these with your own domain-specific categories.

In the config file:

```json theme={null}
{
  "write_key": "your-write-key",
  "self_diagnostics": {
    "signals": {
      "billing_complaint": {
        "description": "User is upset about unexpected charges or billing errors.",
        "sentiment": "NEGATIVE"
      },
      "feature_request": {
        "description": "User requesting a feature that does not exist.",
        "sentiment": "POSITIVE"
      }
    },
    "guidance": "Only report billing issues if the user explicitly mentions charges.",
    "toolName": "__my_report"
  }
}
```

Or via environment variable:

```bash theme={null}
RAINDROP_SELF_DIAGNOSTICS='{"signals":{"billing_complaint":{"description":"Billing issue","sentiment":"NEGATIVE"}}}' claude "do something"
```

Custom signals **replace** the built-in defaults entirely. The `noteworthy` catch-all is always appended automatically. `sentiment` is optional (`"POSITIVE"` or `"NEGATIVE"`). `guidance` adds additional instructions to the tool description. `toolName` overrides the default tool name (`__raindrop_report`).

***

## Self Diagnostics

Self Diagnostics lets your agent proactively report issues — capability gaps, missing context, broken tools, task failures — back to your team as signals in Raindrop.

It's delivered as an MCP server that's registered automatically during `setup`. Claude Code can call the `__raindrop_report` tool to flag issues, and each signal is attached to the current event in your dashboard.

### How it works

The setup command registers a `raindrop-diagnostics` MCP server with Claude Code. When Claude detects an issue during a session, it calls the tool with a category and detail. The signal appears on the corresponding event in Raindrop's Signals dashboard.

### Categories

| Category                 | When to use                                               |
| ------------------------ | --------------------------------------------------------- |
| `missing_context`        | Critical information, credentials, or access is missing   |
| `repeatedly_broken_tool` | A tool has failed persistently across retries             |
| `capability_gap`         | The task requires a tool or permission that doesn't exist |
| `complete_task_failure`  | The agent tried and failed to deliver the result          |
| `noteworthy`             | Something unusual worth flagging for review               |

### Verifying

```bash theme={null}
claude mcp list
```

You should see `raindrop-diagnostics` in the list. Signals appear in the Raindrop dashboard under the event they're attached to.

***

## Uninstalling

**Plugin users:**

```bash theme={null}
claude plugin uninstall raindrop
```

**npm users:**

```bash theme={null}
raindrop-claude-code uninstall      # removes hooks from settings.json + MCP server
npm uninstall -g @raindrop-ai/claude-code
```

***

## Debugging

To see exactly what each hook sends, enable debug logging:

```bash theme={null}
raindrop-claude-code debug-on
```

This pipes hook output to `/tmp/raindrop-hooks.log`. Run a Claude Code session, then inspect the log:

```bash theme={null}
cat /tmp/raindrop-hooks.log
```

To disable:

```bash theme={null}
raindrop-claude-code debug-off
```

***

## Troubleshooting

### Events not appearing

1. **Check your write key** — run `raindrop-claude-code setup` again or verify `~/.config/raindrop/config.json`
2. **Verify hooks are installed** — run `/hooks` inside Claude Code to list active hooks
3. **Enable debug logging** — run `raindrop-claude-code debug-on` and check `/tmp/raindrop-hooks.log`
4. **Check binary is in PATH** — run `which raindrop-claude-code`
5. **Headless mode** — re-run `raindrop-claude-code setup` to ensure hooks are sync (the default since v0.0.7)

### Hook errors

Hook errors are logged to `/tmp/raindrop-hooks.log` when debug is enabled. Run:

```bash theme={null}
raindrop-claude-code debug-on
claude -p "test"
cat /tmp/raindrop-hooks.log
```

***

That's it! Ping us on Slack or [email us](mailto:founders@raindrop.ai) if you need help.
