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

# OR Otel

> Track Claude Code and Codex usage and cost across your organization, teams, and users.

`or-otel` sends usage from **Claude Code** (terminal and Claude Desktop) and **Codex** (terminal and desktop app) to OpenReason, so you can see usage and cost by organization, team, and user. Requests still go directly to Anthropic or OpenAI and are billed to your own subscription.

To bill requests to your org and apply budgets instead, use [`claude-or`](/quickstart/claude-code).

<Warning>
  Once set up, every Claude Code and Codex session on your Mac reports its model, token counts, and prompt text to OpenReason. To send usage without prompt text, see [What gets sent](#what-gets-sent).
</Warning>

## Prerequisites

| Requirement | Details |
| - | - |
| **macOS** | Linux and Windows coming soon |
| **OpenReason API key** | Starts with `sk-or_`. Create one at [admin.openreason.app/dashboard/api-keys](https://admin.openreason.app/dashboard/api-keys), or ask your admin |
| **sudo access** | Used to install `or-otel` and write the Claude Code and Codex config |

<Tip>
  Works with Claude Code and Codex whether they're pre-installed or newly installed after setup.
</Tip>

## Install

<Steps>
  <Step title="Run the installer">
    Open Terminal and run:

    ```bash theme={null}
    curl -fsSL https://get.openreason.app/otel | bash
    ```

    * Enter your password for **sudo** when asked. This installs `or-otel` to `/usr/local/bin`.
    * Paste your **OpenReason API key** when asked. Nothing shows while you paste — that's expected.
    * Enter your sudo password again if asked. This writes the Claude Code and Codex config.

    The installer checks your key against the router and ends with:

    ```text theme={null}
    ✓ Setup complete.
    ```
  </Step>

  <Step title="Restart your AI tools (required)" icon="rotate-right">
    <Warning>
      **Usage isn't tracked until you restart.** Sessions left open from before setup keep their old settings.
    </Warning>

    * **Claude Desktop and Codex app:** fully quit with **Cmd+Q** (closing the window isn't enough), then reopen.
    * **Claude Code and Codex CLI:** open a new terminal window and start a new session.
  </Step>

  <Step title="Check it works">
    ```bash theme={null}
    or-otel doctor
    ```

    Every line should show `✓`, ending with `router accepts exports`.

    Then send one prompt from each tool you use, in a **new** terminal:

    ```bash theme={null}
    claude -p "say hi"
    codex exec "say hi"
    ```

    Open **Audit Log → Events** in the [OpenReason dashboard](https://admin.openreason.app). New rows appear within about 30 seconds, with the model, token counts, and your prompt.
  </Step>
</Steps>

### Install options

Pass options to `or-otel setup` after `bash -s --`, or set environment variables before `bash`:

```bash Usage only, no prompt text theme={null}
curl -fsSL https://get.openreason.app/otel | bash -s -- --no-log-prompts
```

```bash Key up front (CI, MDM, scripted rollout) theme={null}
curl -fsSL https://get.openreason.app/otel | OR_API_KEY=sk-or_... bash
```

```bash A different router theme={null}
curl -fsSL https://get.openreason.app/otel | OR_ROUTER_URL=https://<router-url> bash
```

Use `OR_ROUTER_URL` only if your admin gives you a router URL. The default is `https://api.openreason.app`.

## What gets sent

| | |
| - | - |
| **Sent** | Model, token counts, latency, session ID, your prompt text, and the reply |
| **Not sent** | File contents, tool output, anything outside Claude Code and Codex |
| **Cost** | A list-price estimate — Claude Code's own, and for Codex the OpenAI API price of its tokens. Both count toward your team's OpenReason budget. Anthropic or OpenAI still bills you on your own subscription, not OpenReason |

Prompt and response text is redacted for secrets and kept up to 256k characters each. Longer text is cut and the row is marked truncated.

To send usage only, without text:

```bash theme={null}
or-otel setup --no-log-prompts
```

The choice is remembered across updates. Run `or-otel setup --log-prompts` to turn text back on.

## Commands

| Command | What it does |
| - | - |
| `or-otel setup [--router URL] [--log-prompts \| --no-log-prompts]` | Write the config. Keeps your saved key, router, and prompt setting unless you pass new ones |
| `or-otel status` | Check the key, both configs, and the Codex reply hook are present |
| `or-otel doctor` | `status`, plus installed tools, the last Codex hook run, and a test export to the router |
| `or-otel update` | Install the latest `or-otel` and re-apply the config |
| `or-otel uninstall [--yes]` | Remove the config, your saved key, and `or-otel` itself |
| `or-otel version` | Print the version |

## Update

```bash theme={null}
or-otel update
```

Re-running the install command does the same thing. Both keep your saved key, router, and prompt setting.

## Uninstall

```bash theme={null}
or-otel uninstall
```

Confirms with `[y/N]`, then removes the Claude Code and Codex telemetry config, your saved key (`~/.openreason/otel`), and `or-otel` itself. Claude Code and Codex stay installed and work as normal. Fully quit and reopen them afterwards.

## Troubleshooting

<Accordion title="✗ couldn't download or-otel" icon="triangle-exclamation">
  Check your network or VPN, and that the install URL is the one your admin gave you.
</Accordion>

<Accordion title="or-otel: command not found after install" icon="circle-info">
  Open a new terminal. `/usr/local/bin` is on the default macOS `PATH`. If you've changed yours, run the full path:

  ```bash theme={null}
  /usr/local/bin/or-otel doctor
  ```
</Accordion>

<Accordion title="✗ Key rejected (HTTP 401)" icon="triangle-exclamation">
  Setup shows `rejected this key`, or `or-otel doctor` shows `router rejects the key`. The key is invalid, revoked, or doesn't match the router — for example, a development key against production.

  Create a new key at [admin.openreason.app/dashboard/api-keys](https://admin.openreason.app/dashboard/api-keys), then re-run setup and paste it:

  ```bash theme={null}
  or-otel setup
  ```

  If your admin gave you a different router, add `--router https://<router-url>`.
</Accordion>

<Accordion title="✗ that doesn't look like an sk-or_ key" icon="triangle-exclamation">
  OpenReason API keys start with `sk-or_`. Copy the full key from [admin.openreason.app/dashboard/api-keys](https://admin.openreason.app/dashboard/api-keys) and re-run `or-otel setup`.
</Accordion>

<Accordion title="✗ router unreachable" icon="triangle-exclamation">
  Check your network or VPN and retry. If it persists, tell your OpenReason admin — the router may be down.
</Accordion>

<Accordion title="✗ Claude Code config has no auth header" icon="triangle-exclamation">
  The config was written by an older `or-otel`. Update it:

  ```bash theme={null}
  or-otel update
  ```
</Accordion>

<Accordion title="doctor shows all ✓, but a tool isn't in the audit log" icon="circle-info">
  Fully quit (Cmd+Q) and reopen the tool, then start a **new** session. Terminals must be opened *after* setup to pick up the config.
</Accordion>

<Accordion title="⚠ an MDM profile is installed" icon="circle-info">
  Your company manages Claude Code or Codex centrally, and those settings take priority over `or-otel`. Ask your IT team.
</Accordion>

For anything else, send the output of `or-otel doctor` to your OpenReason admin.

## For admins

<AccordionGroup>
  <Accordion title="Where the config lives" icon="folder">
    `or-otel setup` writes each tool's managed (admin) config. Managed config sits above the user's own `~/.claude` and `~/.codex` settings, so it covers existing and future installs, and users can't switch it off from their own settings.

    | Path | Contents |
    | - | - |
    | `~/.openreason/otel/` | Saved key, router, and prompt setting for re-runs (directory `0700`, files `0600`) |
    | `/Library/Application Support/ClaudeCode/managed-settings.d/openreason-otel.json` | Claude Code `env`: OTLP logs exporter, `http/json`, `<router>/otlp`, auth header, `OTEL_LOG_USER_PROMPTS` |
    | `/etc/codex/managed_config.toml` | An `[otel]` block between `# >>> openreason otel >>>` markers. Other managed Codex settings are kept |
    | `/etc/codex/requirements.toml` | While text is sent: a `Stop` hook that runs `or-otel codex-hook` after each Codex turn to send its reply. Removed with `--no-log-prompts` |

    The managed config files hold the user's key and are readable by other local accounts. On shared machines, push the same settings through MDM instead.
  </Accordion>

  <Accordion title="Unattended installs" icon="robot">
    Pass the key up front to skip every prompt except `sudo`:

    ```bash theme={null}
    curl -fsSL https://get.openreason.app/otel | OR_API_KEY=sk-or_... bash
    ```
  </Accordion>

  <Accordion title="MDM rollout" icon="building">
    Skip the installer and deploy configuration profiles instead:

    * `com.anthropic.claudecode` — the same keys as the Claude Code JSON file above.
    * `com.openai.codex` — `config_toml_base64` holding the `[otel]` block, and `requirements_toml_base64` holding the `Stop` hook for Codex replies. `or-otel` must still be installed for the hook to run.

    An MDM profile overrides the files `or-otel` writes. `or-otel setup` and `or-otel status` warn when one is installed.
  </Accordion>

  <Accordion title="Claude Team and Enterprise orgs" icon="users">
    If your org sends any settings from the claude.ai admin console, Claude Code takes managed settings from there first. `or-otel` puts the auth header in `env` for this reason, because `env` is still merged from the local file.

    To have the whole local file apply, set `"managedSourcesBehavior": "merge"` in the claude.ai admin console.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={2}>
  <Card title="Claude Code with OpenReason" icon="terminal" href="/quickstart/claude-code">
    Route Claude Code through OpenReason instead, so prompts bill to your org's key and per-user budgets apply.
  </Card>
</CardGroup>
