Skip to content

How to monitor Claude Code and Codex usage across a team

Monitor Claude Code and Codex across a team with OpenTelemetry: what to collect, what to keep out, how to read cost, and how to limit unattended runs.

Practical guide · 10 min read

Why coding agents need team-level visibility

One developer running Claude Code in a terminal can see roughly what it costs and what it did. Once a dozen people use it, and Codex also runs on a build server overnight, nobody has that picture any more. The questions become team questions: which machines account for most of the spend this week, where API errors keep repeating, which tools the agent calls most, and what ran while nobody was watching.

The work happens on laptops and servers, not in one place you control, so the answers have to come from the tools themselves. Both Claude Code and Codex can export telemetry. Most of the job is configuration: choose where the data goes, decide what it may keep, and make every machine send it the same way.

What Claude Code and Codex can export with OpenTelemetry

Both tools can send OpenTelemetry data to an endpoint you choose. Claude Code exports metrics and log events once telemetry is switched on, for example in the env block of its settings.json (usually ~/.claude/settings.json). Its metrics include a token counter, claude_code.token.usage, split by type such as input and output, and a cost counter, claude_code.cost.usage. Its events include API requests, API errors and tool results.

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_METRICS_EXPORTER": "otlp",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "https://otel-collector.example.com",
    "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer <token>",
    "OTEL_LOG_USER_PROMPTS": "0",
    "OTEL_LOG_TOOL_DETAILS": "0"
  }
}
Example: Claude Code telemetry in settings.json (placeholder endpoint and token)

Codex is configured through an [otel] section in its config.toml (usually ~/.codex/config.toml). It exports log events such as API requests, streamed response events, tool results and the start of a conversation.

[otel]
log_user_prompt = false
exporter = { otlp-http = { endpoint = "https://otel-collector.example.com/v1/logs", protocol = "binary", headers = { Authorization = "Bearer <token>" } } }
Example: Codex log export in config.toml (placeholder endpoint and token)

Decide what to collect before you turn it on

Telemetry from a coding agent sits very close to your source code, so settle the privacy rules first. A useful team view needs surprisingly little:

  • the event type and when it happened, for example an API request or a failed tool call
  • token counts and the tool’s own cost estimate
  • whether each request or tool use succeeded
  • which machine it came from

Some things are better never collected at all:

  • prompt text, which often contains code, pasted secrets or customer data
  • tool arguments and results, such as shell commands and file contents
  • file paths, which reveal repository layout and sometimes client names
  • user identities such as email addresses, unless you have a specific reason and the team knows

In the examples above, OTEL_LOG_USER_PROMPTS, OTEL_LOG_TOOL_DETAILS and log_user_prompt are set explicitly to keep prompt text and tool details out of the events. Filter at the collector as well, because one machine with prompt logging switched on is enough to put code into your telemetry store. Tell developers what is collected and why before you switch it on.

Read cost figures as estimates

The cost a coding agent reports is an estimate from the tool itself, not a line from your invoice. It can differ from what you are billed, so use it to compare machines and weeks, and reconcile against the provider’s billing when the exact number matters.

Watch how the counters arrive, too. Claude Code’s cost and token metrics come in as separate series from each machine, not as session totals or a daily budget, so summing them without care can double count. A metric that never arrived should show as missing rather than zero: a machine that reports nothing may simply have telemetry switched off.

Unattended runs from cron or systemd need a limit and a stop

Interactive use has a person watching the terminal. A scheduled job that runs Codex against a repository at 2 a.m. does not, and that is where a looping agent or a hung process costs the most. Telemetry tells you about it afterwards; it does not end the run.

Wrap unattended runs in something that enforces a wall-clock limit, ends the whole process tree rather than only the parent, and lets someone stop the run remotely. Record the exit status and whether the expected output file exists, so a job that exited cleanly without producing anything still shows up as a problem.

Put MCP servers behind a gateway

Both tools can launch MCP servers that give the agent tools such as a filesystem, a GitHub client or a database. Each tool call acts on a real system, and the agent’s own telemetry records that a tool ran without giving you a policy over which tools it may call. A gateway that the client launches in place of the MCP server can allow or deny tools by name, count the calls, and report each one.

Set up Claude Code and Codex monitoring with Toolcaise Connect

Toolcaise Connect is a command-line connector that runs on each developer machine or build server and reports to a Toolcaise workspace. On one machine, the setup is:

toolcaise-connect pair
toolcaise-connect service install
toolcaise-connect discover --json
toolcaise-connect adapters enable claude
toolcaise-connect adapters enable codex
Shell

pair prints a code and a link. Approve it in a browser signed in to your workspace and the machine appears under Devices, where it can be revoked later. service install runs the background daemon as a user-level service (a logon task on Windows, a LaunchAgent on macOS, a systemd user unit on Linux), and that daemon uploads what the adapters collect. discover reports which tools it found and changes nothing.

adapters enable claude adds telemetry settings to the env block of Claude Code’s settings.json, and adapters enable codex adds an [otel] section to Codex’s config.toml. Both point the tool at Connect’s local collector with prompt logging switched off. Both refuse to run if the file already has OpenTelemetry settings, so an export your team already uses is never overwritten. Restart the tool afterwards.

toolcaise-connect adapters disable claude (or codex) restores the original file. If you edited the file after enabling, it keeps your edits instead and tells you where its private backup is.

What the local collector accepts and what it discards

The collector listens only on 127.0.0.1:4319, requires a random bearer token that the adapter writes into the tool’s configuration, and rejects requests that carry a browser Origin header. It accepts OTLP over HTTP, as JSON or protobuf without compression, at /otlp/claude/v1/logs, /otlp/claude/v1/metrics and the matching codex paths. The Codex adapter configures log export only.

From logs it keeps an allow-list of events: Claude Code API requests, API errors and tool results, and Codex API requests, streamed response events, tool results and conversation starts. For each one it keeps the event name, the time and whether it was an error. The log body and every other attribute are discarded before anything is written to the local queue. From metrics it keeps Claude Code’s cost estimate and its input and output token counts. Prompts, tool arguments and results, file paths and user identities are never uploaded.

Each adapter’s coverage shows as awaiting telemetry until the first allow-listed event arrives, and goes stale after five minutes without one. toolcaise-connect collection pause stops uploads from a machine and rejects new collection until you run collection resume.

Supervise scheduled Codex runs and MCP servers

For unattended work, toolcaise-connect run wraps the command. This example is a crontab entry for a script that runs Codex against a repository each night. The script is yours and the limits are examples:

0 2 * * * toolcaise-connect run --agent "Nightly Codex" --max-runtime 45m --remote-control --output /srv/reports/nightly.md -- /srv/jobs/nightly-codex.sh
crontab

Connect records the start, end and exit status, reports whether the output file exists and is not empty (it never reads the contents), and stops the command and everything it started when the runtime limit is reached, exiting with 124. With --remote-control, someone can also stop that run from the dashboard (exit code 125); Connect polls for instructions every ten seconds over outbound HTTPS, or up to two minutes apart after failures. If Toolcaise cannot be reached, local limits still hold and the job keeps running.

Token, cost and model limits (--max-total-tokens, --max-cost-usd, --allow-model) work differently: Connect points the command’s OpenAI and Anthropic base-URL variables at a local gateway and meters each call. They only cover model traffic that uses those variables, and a cost limit needs prices you supply in a policy file. If a run reports no model calls, the tool is not going through the gateway, and only the runtime limit and the stop apply to it.

For MCP servers, replace the server’s command in the client’s MCP configuration with toolcaise-connect mcp and pass the original command after --:

toolcaise-connect mcp --name "Filesystem tools" --deny-tools 'shell__*' -- npx -y @modelcontextprotocol/server-filesystem /srv
Command to put in the MCP client configuration

A refused tool is removed from the tool list, and a call to it is answered as a tool error the model can read. --max-tool-calls sets a budget for the session. With --name, each tool call is reported as a span on a run that lasts as long as the MCP server does.

What this setup does not cover

Know these limits before anyone relies on it:

  • The adapters observe only. They cannot pause, stop or cap an interactive Claude Code or Codex session. Limits apply only to commands started with toolcaise-connect run.
  • Claude Code’s cost is the tool’s own estimate, reported as separate series per machine, not a session total, a daily budget or your bill. The Codex adapter reports events without cost.
  • The local collector accepts only OTLP over HTTP for logs and metrics. gRPC, traces, histograms and compressed payloads are refused.
  • Usage is attributed to a paired machine, not to a person, because user identities are not uploaded.
  • When Claude Code or Codex change their telemetry, the adapters may need an update before new or renamed events are counted.
  • The MCP gateway decides by tool name, not by arguments: a permitted tool is permitted whatever it is called with.
  • Connect is currently a preview. Its binaries are not yet code-signed, and running it as a service has not been acceptance-tested on every operating system.

No part of it checks that the changes an agent made are correct. That still takes review.

Frequently asked questions

How do I monitor Claude Code usage across my team?

Switch on Claude Code’s OpenTelemetry export on every machine and send it to one collector that keeps only what you need: event types, token counts, cost estimates, errors and the machine. Keep prompt logging and tool details off. With Toolcaise, pair each machine with toolcaise-connect pair, install the service, and run toolcaise-connect adapters enable claude, which configures the export and filters it before upload.

How do I track Claude Code costs per developer?

Claude Code exports a cost counter, claude_code.cost.usage, that is the tool’s own estimate, so treat it as a comparison figure and reconcile with provider billing when accuracy matters. Toolcaise attributes usage to each paired machine rather than to a named person, because it does not upload user identities; a developer with two machines appears as two devices.

Does Codex support OpenTelemetry?

Yes. Codex reads an [otel] section in its config.toml that sets an OTLP exporter, its endpoint and headers, and whether user prompts are logged. It exports log events such as API requests, streamed response events, tool results and conversation starts. Toolcaise’s Codex adapter configures log export only, with prompt logging off, so in Toolcaise Codex appears as events without token or cost figures.

Can I stop a Claude Code or Codex session that is costing too much?

Not through telemetry. Telemetry, including Toolcaise’s adapters, observes an interactive session but cannot pause or stop it. For scheduled or scripted runs, wrap the command in toolcaise-connect run with a runtime limit: Connect ends the command and everything it started when the limit is reached, and --remote-control lets someone stop it from the dashboard. Token and cost limits apply only to model calls that go through its local gateway.

Does Claude Code telemetry include my prompts and code?

It can, depending on settings. OTEL_LOG_USER_PROMPTS and OTEL_LOG_TOOL_DETAILS control whether prompt text and tool details are included, and setting both to 0 keeps them out. Toolcaise’s adapter sets both to 0, and its local collector keeps only the event name, time and error status from allow-listed log events. Prompts, tool arguments and results, file paths and user identities are never uploaded.

Connect your first agent

Create a free workspace, connect the agent you already run, and watch its next run arrive. Free covers 3 agents, with no card required.