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

# Track your Claude Code usage

> See what you spend per session, which models you hit, how many tokens are cached, and the full prompt + response trail. Two paths, depending on whether you pay Anthropic per token or on a Claude Max / Pro plan.

The Anthropic Console gives you a monthly total, but nothing about which prompt cost what, which model handled which turn, how many tokens came from the prompt cache vs fresh, or what the assistant actually said in long agentic runs. Without that, you can't debug your own agent.

This guide wires Claude Code up so all of that lands on LangWatch, where you can browse:

* Cost per session and per turn
* Model used per turn, including subagents
* Cache writes vs cache reads (cached prompts are 10x cheaper, so you can adjust your setup to maximize it)
* Full prompt body
* Trace tree of tool calls, latencies, and durations
* **Have your agent automatically self-improve by inspecting its own traces, via [LangWatch skills](https://langwatch.ai/docs/skills/directory) or [MCP](https://langwatch.ai/docs/integration/mcp)**

How you pay Anthropic decides which path you walk:

* [Tracking Claude Code usage on pay-per-token API keys](#tracking-claude-code-usage-on-pay-per-token-api-keys)
* [Tracking Claude Code usage on 5x or 20x plans](#tracking-claude-code-usage-on-5x-or-20x-plans)

## Step 0: Get LangWatch

Pick one and stop on `/me`:

**SaaS (fastest).** Sign up at [app.langwatch.ai](https://app.langwatch.ai). You land on `/me`.

**Self-hosted (one command).**

```bash theme={null}
npx @langwatch/server
```

That bootstraps Postgres, ClickHouse, Redis, and the app on `http://localhost:5560`. Open it, sign up with email and password.

<Frame caption="The /me page after sign-up. Empty so far. That changes once Claude Code starts emitting.">
  <img src="https://mintcdn.com/langwatch/knqYTQ0FcDsxQluw/images/ai-governance/post-bypass/01-me-portal.png?fit=max&auto=format&n=knqYTQ0FcDsxQluw&q=85&s=7d5e4cff289dc07c43863ba302445a9c" alt="/me empty landing" width="1280" height="940" data-path="images/ai-governance/post-bypass/01-me-portal.png" />
</Frame>

## Tracking Claude Code usage on pay-per-token API keys

You hold an Anthropic API key and pay per request. This path routes every Claude Code call through a local gateway that holds your key, captures the full request and response server-side, and writes a trace. Cost numbers come straight from Anthropic's response.

### 1.1 Paste your Anthropic key

Open **Settings → Model providers** (URL: `/settings/model-providers`), click the **Anthropic** tile, paste your `sk-ant-` key.

<Frame caption="Model providers screen with Anthropic configured. The sk-ant- key stays on the LangWatch side.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/post-bypass/15-model-providers-configured.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=389823f49d5002b285c0aad0661e1125" alt="Model providers configured" width="2880" height="2200" data-path="images/ai-governance/post-bypass/15-model-providers-configured.png" />
</Frame>

### 1.2 Install the CLI

```bash theme={null}
npm install -g langwatch
```

### 1.3 Log in

```bash theme={null}
langwatch login --device
```

Browser opens with an approval code. Approve it. The CLI caches your refresh token at `~/.langwatch/config.json`. Your Virtual Key is issued the first time you pick the gateway, not now.

<Frame caption="`langwatch login --device` pairs the CLI with your account.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/cli-flow/01-cli-login-device-flow.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=abf05fe7d0cb27ba1cc55e1c40f8c86d" alt="langwatch login device flow" width="4000" height="496" data-path="images/ai-governance/cli-flow/01-cli-login-device-flow.png" />
</Frame>

### 1.4 Run Claude Code through the wrapper

```bash theme={null}
langwatch claude
```

The first run asks how to connect. Pick **Using an API key** for this path. The CLI remembers the answer, so later runs do not ask again.

That spawns Claude Code with `ANTHROPIC_BASE_URL` and `ANTHROPIC_AUTH_TOKEN` set so every request goes through the gateway. UX is identical to `claude` on its own: same REPL, same keybinds, same agent loop.

<Frame caption="Interactive Claude Code session via the wrapper. The wrapper injects the gateway env and gets out of the way.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/cli-flow/06-tmux-langwatch-claude-real.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=7088fd480f2aab28bf338bf660ef2dc3" alt="langwatch claude tmux" width="4000" height="1094" data-path="images/ai-governance/cli-flow/06-tmux-langwatch-claude-real.png" />
</Frame>

### 1.5 Open `/me`

Within a few seconds:

* **Spent this month** has a number.
* **Recent activity** has a row per Claude Code turn, with model, tokens, dollar cost.
* **By tool** breaks down spend per model.

<Frame caption="My Usage panel after one Claude Code session. Exact cost per call, per-model breakdown, daily spend.">
  <img src="https://mintcdn.com/langwatch/knqYTQ0FcDsxQluw/images/ai-governance/post-bypass/37-me-usage-scrolled.png?fit=max&auto=format&n=knqYTQ0FcDsxQluw&q=85&s=da3cad48ed2c95e0c0a873140c4ef39e" alt="My Usage populated" width="1280" height="1262" data-path="images/ai-governance/post-bypass/37-me-usage-scrolled.png" />
</Frame>

Click **Traces** in the sidebar for the per-request view. Each turn lands as a `gen_ai.*` span with prompt, response, model, tokens, and dollar cost.

<Frame caption="Trace detail for one Claude Code turn through the gateway. Prompt and response inline, tokens split between cache_creation and cache_read, exact cost.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/cli-flow/07-trace-detail-pong-via-gateway.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=d89681d1d979e0cd102a79fd04570bfc" alt="Path 1 trace detail" width="1280" height="720" data-path="images/ai-governance/cli-flow/07-trace-detail-pong-via-gateway.png" />
</Frame>

That is the loop. Every future `langwatch claude` session writes here. Skip to [What you can do with this](#what-you-can-do-with-this).

## Tracking Claude Code usage on 5x or 20x plans

You pay Anthropic flat per month on a Max or Pro plan. The Anthropic Console only shows a monthly total, no per-call breakdown. The only way to see per-call detail is to capture Claude Code's own OpenTelemetry output and let LangWatch render it.

You do not need a Virtual Key for this path. The wrapper asks once how to connect, and this path is the answer **Using a Claude subscription**: your plan stays as it is and LangWatch receives telemetry only.

### 2.1 Install the CLI

```bash theme={null}
npm install -g langwatch
```

### 2.2 Log in

```bash theme={null}
langwatch login --device
```

Same browser approval as Path 1; no API key needed.

<Frame caption="`langwatch login --device` paired with your account.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/cli-flow/01-cli-login-device-flow.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=abf05fe7d0cb27ba1cc55e1c40f8c86d" alt="langwatch login device flow" width="4000" height="496" data-path="images/ai-governance/cli-flow/01-cli-login-device-flow.png" />
</Frame>

### 2.3 Run Claude Code through the wrapper

```bash theme={null}
langwatch claude
```

Pick **Using a Claude subscription** when the wrapper asks. Your Claude Code session keeps using your Max plan unchanged. LangWatch reads the OTel log records Claude Code emits and renders them.

<Frame caption="Interactive Claude Code session under the subscription path. Same wrapper, no API key.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/cli-flow/08-tmux-claude-pathb-otel-real.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=148f689d6af7e79d3eaccb9001f52c9d" alt="langwatch claude tmux path 2" width="4000" height="1094" data-path="images/ai-governance/cli-flow/08-tmux-claude-pathb-otel-real.png" />
</Frame>

### 2.4 Open `/me`

Within \~30 seconds of your first turn:

* **Spent this month** has a number from Claude Code's own `cost_usd` field.
* **Recent activity** has a row per turn.
* **By tool** shows the model breakdown.

<Frame caption="My Usage panel populated under the subscription path. Same surface as Path 1; the cost number comes from Claude Code's own usage event.">
  <img src="https://mintcdn.com/langwatch/knqYTQ0FcDsxQluw/images/ai-governance/post-bypass/37-me-usage-scrolled.png?fit=max&auto=format&n=knqYTQ0FcDsxQluw&q=85&s=da3cad48ed2c95e0c0a873140c4ef39e" alt="My Usage populated" width="1280" height="1262" data-path="images/ai-governance/post-bypass/37-me-usage-scrolled.png" />
</Frame>

<Frame caption="Trace detail under the subscription path. Model, input tokens, output tokens, cache_creation_tokens, cache_read_tokens, cost_usd, and the prompt body all rendered from Claude Code's OTel log records.">
  <img src="https://mintcdn.com/langwatch/peNTdoxW72EUqULT/images/ai-governance/post-bypass/14-claude-pathb-trace-detail-storegate-fix.png?fit=max&auto=format&n=peNTdoxW72EUqULT&q=85&s=78487cb1ba791606ad19ef001b133f59" alt="Path 2 trace detail" width="2880" height="2200" data-path="images/ai-governance/post-bypass/14-claude-pathb-trace-detail-storegate-fix.png" />
</Frame>

## Headless machines and team projects

The wrapper wires a tool when it starts it, which needs somebody at the keyboard. `langwatch instrument claude` writes the same wiring into `~/.claude/settings.json` and exits, so a plain `claude` run on that machine reports to LangWatch. Use it on a server that holds many agents, in a machine image, or in a configuration management run.

```bash theme={null}
langwatch instrument claude
```

By default the telemetry goes to your personal workspace, which needs `langwatch login --device`. Pass one scope flag to change that:

| Command                                              | Destination                     | Needs a login |
| ---------------------------------------------------- | ------------------------------- | ------------- |
| `langwatch instrument claude --project <id-or-slug>` | A team project                  | Yes           |
| `langwatch instrument claude --key ik-lw-...`        | The project that owns the key   | No            |
| `langwatch instrument claude --personal`             | Back to your personal workspace | Yes           |

`--project` creates an ingest key for this device and holds Claude Code to that project. LangWatch creates one key per device and never replaces the key of another device, so a whole fleet can report to one project:

```bash theme={null}
langwatch instrument claude --project acme-app
```

`--key` takes an ingest key you paste, or the `LANGWATCH_INGEST_KEY` environment variable, and needs no login at all. Add `--endpoint <url>` for a self-hosted instance. The wrappers accept `--project` and `--personal` too, so `langwatch claude --project acme-app` pins the project and then starts Claude Code.

`langwatch logout` removes every wiring target the CLI wrote. Full detail is on the [Claude Code integration guide](/docs/integration/tools/integrations/claude-code).

## Per-repo telemetry with plain `claude` (no wrapper)

Use this when you have both work and personal repos on the same machine, want telemetry on for specific repos only, run plain `claude` (no wrapper), want the configuration auto-applied per repo at launch with no leak to personal repos.

This is a **delivery method**, not a third billing path. It works under either Path 1 or Path 2's billing model. Instead of the `langwatch claude` wrapper injecting environment variables at spawn time, Claude Code reads them from `.claude/settings.json` in your project root at launch. The LangWatch-specific wiring connects to the **project** OTLP endpoint (`/api/otel/v1/traces`). For why the project endpoint is the correct home for Claude Code's own usage telemetry (versus the governance IngestionSource plane), see [Choosing the right OTel endpoint](/docs/observability/trace-vs-activity-ingestion). For how Claude Code's `env` block works and its settings-precedence rules, see the [Claude Code settings reference](https://code.claude.com/docs/en/settings). This section documents only the LangWatch wiring.

<Info>A repo with no `.claude/settings.json` `env` block, run with plain `claude`, emits zero telemetry to LangWatch.</Info>

### Get your project key

The key you need is a standard LangWatch project API key (`sk-lw-…`). Mint it at [app.langwatch.ai/authorize](https://app.langwatch.ai/authorize), the same self-serve page that produces `LANGWATCH_API_KEY` in the quick-start guide.

Minting requires a live device session. If the mint returns 401, re-run `langwatch login --device` to refresh it. Once minted, **ingestion does not need a live session**. The key authenticates the OTLP endpoint standalone, so your `claude` sessions keep sending traces even after the device session expires.

An `ik-lw-` write-only ingest key also authenticates the project OTLP endpoint, and it is the safer one to put in a settings file, because it can create traces in one project and nothing else. `langwatch instrument claude --project <id-or-slug>` mints one for you. See [API keys](/docs/platform/api-keys).

### The two-file recipe

Commit `.claude/settings.json` with the exporter wiring, and keep the bearer token, the `CLAUDE_CODE_ENABLE_TELEMETRY` enable flag and **every content flag** in a gitignored `.claude/settings.local.json`. Telemetry is **off by default**: nothing exports until the enable flag is set, so a fresh clone carrying only the committed `settings.json` sends nothing.

The committed file decides the shape of the export. What that export carries is decided by four flags, and they stay out of the repository so each person turns them on for themselves: `OTEL_LOG_USER_PROMPTS` puts prompt text on the wire, `OTEL_LOG_TOOL_DETAILS` and `OTEL_LOG_TOOL_CONTENT` put the input and output of every tool call on it, and `OTEL_LOG_RAW_API_BODIES` puts the Messages API request and response JSON on it. Inline bodies are truncated at 60 KB (`CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` raises the limit, `file:<dir>` writes untruncated bodies to disk instead) and extended thinking is redacted.

<Warning>Those four flags are what put your session content in LangWatch: prompt text, the input and output of every tool call, including file contents, and the model request and response bodies of every turn. A committed content flag does not switch telemetry on by itself, because Claude Code exports nothing until `CLAUDE_CODE_ENABLE_TELEMETRY` is set. It does not have to be set in the repository for that to happen, though: a managed settings file, a shell export, or a contributor's own `~/.claude/settings.json` can each turn telemetry on, and from that moment a content flag sitting in the committed file applies to everyone who cloned the repo. That is why the recipe keeps all four in each person's own gitignored file.</Warning>

`settings.local.json`'s `env` merges per-key with `settings.json`'s `env`, so the local flags combine with the committed ones rather than replacing them.

**`.claude/settings.json`** (commit this):

```json theme={null}
{
  "env": {
    "CLAUDE_CODE_ENHANCED_TELEMETRY_BETA": "1",
    "OTEL_TRACES_EXPORTER": "otlp",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "https://app.langwatch.ai/api/otel",
    "OTEL_LOGS_EXPORT_INTERVAL": "1000",
    "OTEL_METRIC_EXPORT_INTERVAL": "2000",
    "OTEL_RESOURCE_ATTRIBUTES": "project.repo=my-repo-name,cost_center=my-team"
  }
}
```

<Info>**`CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` is an experimental Claude Code flag, and it is the one that turns spans on.** Without it `OTEL_TRACES_EXPORTER` does nothing and `OTEL_LOG_TOOL_CONTENT` has no span events to write to, so you get flat log records instead of a trace: no tool call tree, no latencies, and every subagent folded into the main session rather than branching off it. Keep it when you trim the rest of the block.</Info>

The two export intervals set how often Claude Code flushes; the defaults are 5 seconds for logs and 60 seconds for metrics, which is long enough that a first check looks like a failure.

For self-hosted (`npx @langwatch/server`), replace the endpoint with `http://localhost:5560/api/otel`. The SDK auto-appends `/v1/traces`, `/v1/logs`, `/v1/metrics`. Never write the per-signal path yourself.

**`.claude/settings.local.json`** (gitignore this: add `.claude/settings.local.json` to `.gitignore`):

```json theme={null}
{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_LOG_USER_PROMPTS": "1",
    "OTEL_LOG_TOOL_DETAILS": "1",
    "OTEL_LOG_TOOL_CONTENT": "1",
    "OTEL_LOG_RAW_API_BODIES": "1",
    "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer sk-lw-…",
    "OTEL_RESOURCE_ATTRIBUTES": "project.repo=my-repo-name,cost_center=my-team,enduser.id=you@example.com"
  }
}
```

<Warning>**`OTEL_RESOURCE_ATTRIBUTES` is not merged across files. The higher-precedence file fully replaces it.** `settings.local.json` wins over `settings.json`, so if you set `OTEL_RESOURCE_ATTRIBUTES` in both, the local file's value completely replaces the committed one. Carry all three attributes (`project.repo`, `cost_center`, `enduser.id`) together in the local file, or `project.repo` is silently dropped from every span.</Warning>

### Verify

Run `claude` for at least one turn, then send a test trace or inspect the OTLP response. Real success requires **two conditions** to both be true:

1. The response body contains `"Trace received successfully."` (not just HTTP 200).
2. `partialSuccess.rejectedSpans` equals `0` over a **non-empty** body (at least one span submitted).

A bare HTTP 200 is not proof. An empty payload returns `{"message":"No traces to process"}` with 200, and a malformed span returns `rejectedSpans:1` with 200. Both are silent failures.

View confirmed traces in `/traces` and cost attribution in `/me`.

`langwatch ingest list` is **empty** for this path, which is expected. `ingest list` surfaces governance IngestionSources only (the `lw_is_` plane); project-plane traces never create an IngestionSource. Verify via `/traces` and `/me`, not `ingest list`.

### Gotchas

**Claude Code reads `settings.json` `env` at launch.** A session already running when you add or change the `env` block emits nothing until you restart `claude`. If telemetry is missing after editing the file, exit and relaunch.

**`.gitignore` covering all of `.claude/` silently swallows the committed `settings.json`.** Some repos ignore the entire `.claude/` directory for privacy. That prevents `git add` from staging `settings.json`, so teammates never inherit the telemetry flags, yet local telemetry still works for you (the file is present on disk), so you won't notice. Fix: either `git add -f .claude/settings.json` to force-track it, or, if you want the file tracked by default, fix the `.gitignore` itself. A bare `!.claude/settings.json` negation is a no-op here, because git won't descend into an excluded directory to re-include a file under it. You have to un-ignore the directory first, then re-ignore the secret files:

```gitignore theme={null}
.claude/
!.claude/                       # un-ignore the dir so specific files can be re-included
.claude/settings.local.json     # re-ignore the secret (personal/token) file
.claude/*.lock                  # re-ignore other previously-covered files (e.g. scheduled_tasks.lock)
```

After this, `git check-ignore .claude/settings.json` reports it is no longer ignored (so it commits), while `settings.local.json` stays ignored (so your token is safe).

**Shared key vs key per repo.** One `sk-lw-` key can serve any number of repos: attribution rides on the `project.repo` resource attribute, not the key itself. However, revoking a shared key (app/dashboard only, no CLI revoke) kills telemetry for all repos using it. If you need isolated blast radius, mint a separate key per repo.

**Telemetry is scoped to the launch directory, not the git repository identity.** Claude Code resolves `.claude/settings.json` by walking up from the working directory at launch, so starting from a subdirectory still works via walk-up. A git worktree of the same repo is a separate directory tree; its gitignored `settings.local.json` does not carry over from the main worktree, so telemetry silently won't apply in the worktree unless you re-wire it there. `project.repo` is a hand-set label in `OTEL_RESOURCE_ATTRIBUTES`. It is not derived from the git remote or any git metadata.

## What you can do with this

Whichever path you walked, the data is now sitting on `/me` and `/traces`. Some things you can do with it that Claude Code does not give you on its own:

### Find expensive sessions

`/traces` is the right surface for this: filter by cost, sort, drill into any session to see exactly what was sent and what came back. Useful when one session burns through an unexpected amount of context, or when you want to audit a whole day of agent activity.

### Audit cache hit ratio

The trace metadata includes `cache_creation_tokens` and `cache_read_tokens` separately. Anthropic prompt caching reads at roughly 0.1x and writes at roughly 1.25x of the regular input rate, so the split is the difference between expensive and cheap turns. If your cache\_read ratio is low, your prompts are probably changing the cacheable prefix between turns.

### See what the agent actually sent

You can read every prompt the agent issued, including the long system prompt and any tool definitions it injected.

### Set a personal budget

`/me` → **Settings** → **Personal budget**. Set a monthly cap.

* **Path 1**: the gateway enforces it. Requests fail with `budget_exceeded` once you cross.
* **Path 2**: alerts at 80% and 100%. Claude Code calls keep flowing; Anthropic does not let the receiver gate them.

### Ask your own agent where your tokens went

The same CLI that captured your sessions can read them back, authenticated by your device login, with no API key to configure (an explicit `LANGWATCH_API_KEY` still wins when you set one). Paste one prompt into Claude Code and it answers which sessions were the most expensive, what ran above 150k context, which subagents consumed the most, and more. See [Explore your usage with your own agent](/docs/ai-governance/explore-your-usage-with-your-own-agent).

### Have the agent improve itself off its own traces

Point Claude Code (or any agent) at LangWatch's [skills directory](https://langwatch.ai/docs/skills/directory) so it can reach into its own past traces, find where it wasted tokens or made the wrong call, and update its own behaviour. The [LangWatch MCP](https://langwatch.ai/docs/integration/mcp) does the same thing through the MCP protocol.

### Use the same wrapper for other CLIs

Same pattern works for the other agent CLIs you might be running. Each wrapper asks the same question on its first run, and `langwatch instrument <tool>` writes the subscription-path wiring without starting anything.

| Command              | Using an API key                                                                   | Using your own subscription                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `langwatch claude`   | gateway via `ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN`                          | OTLP via `CLAUDE_CODE_ENABLE_TELEMETRY` + `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` (spans, and with them the tool call tree and subagent attribution) + an ingest key on `OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer ik-lw-…"` + the four `OTEL_LOG_*` content knobs (`USER_PROMPTS`, `TOOL_DETAILS`, `TOOL_CONTENT`, `RAW_API_BODIES`) so user prompt text, tool input and output content, and assistant response text all land on the wire, with bodies truncated at 60 KB and extended thinking redacted. See [Claude Code](/docs/integration/tools/integrations/claude-code) |
| `langwatch codex`    | gateway via `OPENAI_BASE_URL` + `OPENAI_API_KEY`                                   | OTLP via the `[otel]` block in `~/.codex/config.toml`, plus a turn program that recovers the conversation Codex never exports. See [OpenAI Codex](/docs/integration/tools/integrations/openai-codex)                                                                                                                                                                                                                                                                                                                                                                                |
| `langwatch copilot`  | gateway via `COPILOT_PROVIDER_*` keys, which moves the spend off your Copilot seat | OTLP via `COPILOT_OTEL_ENABLED` and a scoped shell function. See [GitHub Copilot](/docs/integration/tools/integrations/github-copilot-cli)                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `langwatch code`     | not available for Copilot Chat                                                     | OTLP for the Copilot Chat extension in Visual Studio Code. See [GitHub Copilot](/docs/integration/tools/integrations/github-copilot-cli)                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `langwatch gemini`   | gateway via `GOOGLE_GEMINI_BASE_URL` + `GEMINI_API_KEY`                            | OTLP with native `gen_ai.*` attributes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `langwatch opencode` | gateway via `OPENAI_*` + `ANTHROPIC_*` env pairs                                   | OTLP for the model calls and the tool calls, with opencode's own internal spans filtered out. See [opencode](/docs/integration/tools/integrations/opencode)                                                                                                                                                                                                                                                                                                                                                                                                                         |

## Privacy

Everything you mint here is scoped to your personal project. If you signed in via a shared org workspace, switch to your personal workspace before running `langwatch login` so the wrapper binds to the right account; the workspace picker is at the top of the sidebar.

For self-hosted (`npx @langwatch/server`), nothing leaves your machine. Postgres, ClickHouse, and Redis all bind to localhost.

## Troubleshooting

**Device login approval fails with "AI-tools (device) login needs governance enabled" (self-hosted).** Your server runs a LangWatch version that ships governance off by default. Update it (`npx @langwatch/server@latest`) or set `RELEASE_UI_AI_GOVERNANCE_ENABLED=1` in `~/.langwatch/.env` and restart the server, then re-run `langwatch login --device`.

**Nothing in Recent activity after 30 seconds.** Confirm the wrapper spawned with the right env. Open `~/.langwatch/config.json`: Path 1 needs a `default_personal_vk` block, Path 2 needs the wrapper to have minted an ingest key (`ik-lw-…`) on first run. If neither shows up, re-run `langwatch login --device` and then `langwatch claude` again. `langwatch instrument claude` writes the same Path 2 wiring on its own and prints the file it wrote and the workspace the telemetry goes to.

**401 from the gateway (Path 1).** Your Virtual Key probably rotated. Re-run `langwatch login --device` or re-mint the Virtual Key from `/me` → Model providers.

**Cost shows \$0 even though traces land (Path 2).** Model alias in the span does not match a current entry in LangWatch's cost catalog. Check `gen_ai.request.model` on the span; current-gen identifiers (`claude-sonnet-4-6`, `claude-opus-4-7`, `claude-haiku-4-5`) match. Legacy aliases (`claude-3-5-sonnet-20241022`) silently return NULL cost.

**Self-hosted: app starts but `/me` is empty.** You probably signed up with the wrong provider. `npx @langwatch/server` only enables email + password by default. Sign up with that.

For deeper failure modes see [CLI debug](/docs/ai-governance/cli-debug) and [Ingestion Templates](/docs/ai-governance/ingestion-templates).
