How to Track, Audit, and Govern Claude Code Costs Across Your Organization

The first problem teams hit when Claude Code spreads across an organization is simple: nobody knows who is using it, how much, or what it costs. This guide walks through it at the level of actual configuration — from confirming how you're billed, to distributing OpenTelemetry settings, to the decisions you need to make before enabling audit logs.
Contents
- "Cost management" for Claude Code is really three layers
- Start by confirming how you're billed
- Compare the ways to get visibility
- What Claude Code can export over OpenTelemetry
- Roll the configuration out company-wide
- Decide these things before enabling audit logs
- Where governance actually happens
- Rollout checklist
"Cost management" for Claude Code is really three layers
When someone says "we need to manage our Claude Code costs," three different jobs are usually bundled together. Separating them first is what keeps you from picking the wrong tool.
- Confirming the bill — what you actually get charged. Only your provider's billing console (Anthropic, AWS, Google Cloud) is authoritative.
- Seeing usage and estimated cost — who uses which model, and how much. This is what drives improvement, chargeback, and investment decisions.
- Governing — spend limits, enforced configuration, blocked operations. The machinery that actually stops things.
This article focuses on layer 2, while keeping its boundary with 1 and 3 explicit. The most expensive misconception at rollout time is assuming that a dashboard will stop overspending.
Start by confirming how you're billed
How Claude Code is billed — and where you can see the numbers — depends on how developers authenticate. In a company-wide rollout it's common for several methods to coexist. Find yourself in this table first.
| Your setup | How spend appears | How caps behave | Per-user reporting |
|---|---|---|---|
| Claude for Teams / Enterprise (seats) | Usage inside the seat allowance isn't metered in dollars. Turning on usage credits surfaces a spend report for the overage (per user and per model, updated daily) | The seat allowance is the default ceiling. With usage credits on, you can set spend limits at the org, group, or member level | Spend report CSV / Enterprise Analytics API (Enterprise) |
| Claude Console (API key) | Console usage page | Workspace spend limits (set on the Claude Code workspace) | Console dashboard / Claude Code Analytics API |
| Amazon Bedrock / Google Cloud / Microsoft Foundry | Your cloud billing console | Your cloud's budget controls — mostly alerting; crossing a threshold generally doesn't stop spend | OpenTelemetry or an LLM gateway |
The first row is where people get tripped up: on seat-based plans, usage inside the allowance is never expressed in dollars. If you want per-user spend as a number, you either turn on usage credits and measure the overage, or you use telemetry estimates. Adoption metrics — daily active users, sessions, code contribution — live on a separate dashboard from spend.
Anthropic's own documentation notes that OpenTelemetry export works on every setup and is the only option that streams per-user token and cost metrics into your own observability stack in near real time. The flip side: usage through a cloud provider is not covered by Anthropic's analytics dashboards at all.
Know the going rate
For budgeting, the published figures are a useful anchor (as of August 2026). Across enterprise deployments the average is about $13 per developer per active day and $150–250 per developer per month, with 90% of users staying under $30 per active day. Measure your own baseline with a small pilot group before extrapolating to the whole company.
Check the auth method with /status
/status shows how a given machine is authenticated. An API key set in the environment can take precedence over a subscription, which means a developer can be generating metered API spend without realizing it. Checking this on a few representative machines before rollout prevents a class of surprise invoices.
Compare the ways to get visibility
There is more than one way to answer "who is using how much," and they cover different ground. Look at what already exists before building anything.
Anthropic's built-in analytics
Claude for Teams and Enterprise include an analytics dashboard in the admin console (daily active users, sessions, contribution metrics, exportable as CSV). The dollar-denominated spend report appears once usage credits are turned on, and it covers spend beyond the seat allowance. On Enterprise, the Analytics API returns per-user usage and cost programmatically. Console (API key) customers get the Console dashboard and the Claude Code Analytics API. Start here — if this covers your needs, you don't need anything else. And if you're still deciding which plan to sign in the first place, see Claude Team vs. Enterprise.
Aggregate local history with ccusage
ccusage is an open-source CLI that reads the Claude Code history on a machine and reports tokens and estimated cost by day, month, and session. It's the fastest way for an individual to understand their own usage. Because it reads local data, it isn't aimed at company-wide distribution, centralized auditing, or access control.
Send OpenTelemetry to your own stack
Claude Code can export OpenTelemetry metrics, logs, and traces. Point OTLP at your own OpenTelemetry Collector and feed Prometheus, Grafana, and a log backend, and you get maximum freedom. You also take on the Collector, the time-series database, dashboards, log search, retention and deletion, and access control — designed and maintained by you.
Send OTLP to a managed backend
The exporter configuration stays identical to the self-hosted route; ingestion, storage, dashboards, and search are handled for you. Aimeterly sits here: it receives the OTLP that Claude Code sends once telemetry is enabled, and turns it into usage, estimated cost, and productivity dashboards, plus audit-log search over the content types your organization turns on in its settings.
| Approach | Primary use | Org-wide | Audit detail | Authoritative billing | Can stop spend | Setup effort |
|---|---|---|---|---|---|---|
| Built-in analytics | Org usage and spend | Yes | Limited | Via your provider | Plan-dependent | Low |
| ccusage | Local, per-machine totals | Partial | Local history only | No | No | Low |
| Self-hosted OTel | Full control and integration | Yes | As designed | No | Separate | High |
| Managed OTel (e.g. Aimeterly) | OTLP dashboards and audit search | Yes | Within what you enable | No (estimates) | No | Low–medium |
| Provider budget controls | Actual spend management | Yes | No | Yes | Depends on provider | Varies |
The columns to read carefully are "Authoritative billing" and "Can stop spend." No telemetry tool is your billing system of record, and none of them stops spending. Both belong on the provider side. What a provider console tends not to give you is near-real-time export into your own stack, aggregation along your own dimensions such as team or department, and event-level audit detail. That is the gap telemetry fills.
How the four differ on refresh rate, lookback window, and who can read the numbers is covered in Four Ways to Track Claude Code Cost, Compared — read that first if you're still deciding. You can see what these dashboards look like on the demo (demo data) page.
What Claude Code can export over OpenTelemetry
Before distributing any configuration, know what actually leaves the machine. Claude Code sends no OpenTelemetry at all until CLAUDE_CODE_ENABLE_TELEMETRY=1 and an exporter are configured. Once enabled, it has three channels — metrics, events (logs), and traces — and every content-logging flag is off by default, so what you get initially is metadata with no message content. The full inventory lives in the monitoring documentation.
Eight standard metrics
| Metric | Unit | What it tells you |
|---|---|---|
claude_code.session.count | count | Sessions started — how much the tool is actually used |
claude_code.token.usage | tokens | Input, output, and cache read/write breakdown |
claude_code.cost.usage | USD | Estimated cost at standard list rates |
claude_code.lines_of_code.count | count | Lines added and removed |
claude_code.commit.count | count | Commits created |
claude_code.pull_request.count | count | Pull requests created |
claude_code.code_edit_tool.decision | count | Edit suggestions accepted or rejected |
claude_code.active_time.total | s | Time actually spent working |
These carry attributes such as user.email, user.id, session.id, model, terminal.type, and organization.id. You can add your own dimensions — OTEL_RESOURCE_ATTRIBUTES=department=platform, for example — to segment by team or department.
Events and content logging are separate things
Alongside metrics, Claude Code emits events as logs: claude_code.user_prompt, claude_code.assistant_response, claude_code.tool_result, claude_code.api_request, claude_code.api_error, and claude_code.tool_decision (the short forms such as user_prompt appear in each record's event.name attribute). The important part is that prompt and response text is not included by default. Recording content requires explicitly enabling these variables:
| Variable | What gets recorded |
|---|---|
OTEL_LOG_USER_PROMPTS | The prompt text a user submitted |
OTEL_LOG_ASSISTANT_RESPONSES | Assistant response text. When unset, it inherits the value of `OTEL_LOG_USER_PROMPTS` |
OTEL_LOG_TOOL_DETAILS | Tool parameters, MCP and skill names, tool input |
OTEL_LOG_TOOL_CONTENT | Tool input and output content. Requires OTEL_TRACES_EXPORTER=otlp and CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1 alongside it, since it travels over traces |
OTEL_LOG_RAW_API_BODIES | The raw Messages API request and response JSON, conversation history included. Setting file:<dir> also writes untruncated bodies to local disk |
Trim the attributes
Metric attributes drive cardinality, which drives cost and performance on some backends. You can drop session IDs with OTEL_METRICS_INCLUDE_SESSION_ID=false and account UUIDs with OTEL_METRICS_INCLUDE_ACCOUNT_UUID=false. If you're sending to your own stack, decide this before you start collecting.
Roll the configuration out company-wide
Telemetry configuration is environment variables. Asking every developer to set them by hand doesn't scale, so you distribute them as managed settings. The JSON payload is identical regardless of the delivery method.
Minimum configuration
{
"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://<your-endpoint>",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer <token>"
}
}This uses the same schema as settings.json, so it works as-is with either delivery method below. The token in OTEL_EXPORTER_OTLP_HEADERS is a secret: keep it out of your repository, and check who can reach the distribution channel.
Option A: server-managed settings (Teams / Enterprise)
On Claude for Teams or Enterprise, paste the JSON into Admin Settings → Claude Code → Managed settings on claude.ai and every user receives it (server-managed settings documentation). Clients fetch at startup and poll hourly during active sessions. This suits organizations without MDM, or fleets that include unmanaged devices. Only Owners and Primary Owners can edit it.
Option B: endpoint-managed settings (MDM)
If you run an MDM, deliver the same JSON through a macOS configuration profile, a Windows registry policy, or a managed-settings.json at the OS-level managed path. Because the file can be protected at the OS level, this gives stronger guarantees.
When nothing shows up
- OpenTelemetry configuration, unlike most settings, requires a full restart to take effect.
- Run
claude --debugto surface exporter errors when you're unsure whether anything is being sent. - If a developer has overridden the endpoint in personal settings, setting
OTEL_EXPORTER_OTLP_ENDPOINTin managed settings strips the conflicting developer-set per-signal endpoints at startup (v2.1.217+). - If a provider variable such as
CLAUDE_CODE_USE_BEDROCKor a non-defaultANTHROPIC_BASE_URLis exported in the shell, the server-managed settings fetch is skipped entirely. - Check whether
claude_code.session.countis climbing on the receiving end first. If it is, the path works and you're down to an attribute problem.
Bedrock, Google Cloud, and Foundry
Server-managed settings are not available with third-party model providers — Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or a custom endpoint. There you either deliver endpoint-managed settings through MDM or run a self-hosted gateway. These setups also fall outside Anthropic's analytics dashboards, which leaves OpenTelemetry or an LLM gateway as the practical routes to per-user cost attribution.
If you'd rather not build and run the receiving end, Aimeterly's setup guide covers it: creating an organization issues an endpoint and an ingest token immediately, so replacing the <...> placeholders above and distributing gets the ingestion path working. Per-user aggregation still needs the identity work described just above.
Decide these things before enabling audit logs
Recording prompts and responses lets you reconstruct what was asked and what happened. It also means source code, customer data, credentials, and personal information may end up in the record. Being able to enable something and being allowed to enable it are different questions.
The default is: no content
Content logging is split mainly into four types — prompts, responses, tool details, and tool content — and all four are off by default (so is OTEL_LOG_RAW_API_BODIES, which this guide never enables). Rather than switching everything on, work backwards from what you actually need to answer. If the question is "what instructions were given," prompts alone are enough (with OTEL_LOG_ASSISTANT_RESPONSES=0 set explicitly, as noted above).
Settle these first
- Purpose — write down why you're recording (incident investigation, data-exfiltration review, demonstrating policy compliance).
- Scope — which of the four types, and for whom: the whole company or specific teams.
- Who can read it — admins only, or managers too? Does your tooling separate those roles?
- Retention and deletion — how long you keep it, the deletion procedure, and who can run it.
- Notifying employees — communicate purpose, scope, and audience in advance. Check with legal and HR whether employment agreements or works-council consultation apply.
Don't wire productivity metrics into performance reviews
Lines of code, commits, pull requests, and suggestion-acceptance rates are genuinely useful for gauging adoption and spotting people who need support. As individual performance measures they distort quickly — they reward writing more lines and committing more often. Keep them at the level of organizational trends, and say explicitly at rollout that they won't be used as direct input to performance reviews. That single statement does more for adoption than any dashboard.
Where governance actually happens
Visibility and control are different layers. A dashboard tells you what happened; it stops nothing. Here's where each thing you might want actually takes effect.
| What you want | Where it happens |
|---|---|
| Actually stop spending | Console workspace limits; the Teams / Enterprise seat allowance and usage-credit spend limits |
| Get told when spend climbs | Your cloud's budget controls (mostly alerting — crossing a threshold generally doesn't stop anything) |
| Block dangerous commands and file access | permissions.deny in managed settings (e.g. Read(./.env), Bash(curl *)) |
| Prevent skipping permission prompts | disableBypassPermissionsMode and allowManagedPermissionRulesOnly in managed settings |
| Hook operations for logging or validation | hooks in managed settings (e.g. an audit script after every edit) |
| Standardize the default model | The env block in managed settings (ANTHROPIC_MODEL, etc.) |
| Know who spent what | Built-in analytics, OpenTelemetry |
| Reconstruct what was asked in a past session | Audit logs, once content logging is enabled |
Which means the right thing to ask of a telemetry tool isn't enforcement — it's being able to confirm afterwards that policy was actually followed. Put enforcement in the provider console and managed settings; put verification in telemetry. That division holds up best over time.
Rollout checklist
The same material, in the order you'd work through it. Clearing these top to bottom avoids most of the rework.
- Confirmed the auth method and who gets billed (
/status, plan, any cloud-provider routing) - Set spend limits on the provider side, and know which ones actually stop spend versus merely alert
- Chose the telemetry destination and reviewed who can reach the token
- Picked exactly one delivery method for managed settings per group of clients (server-managed or MDM)
- Warned developers about the approval dialog, if you're delivering a non-empty endpoint through server-managed settings
- Fully restarted Claude Code on the target machines after delivery (OpenTelemetry settings don't apply until you do)
- Confirmed
claude_code.session.countis arriving at the receiving end - Verified in a pilot that identifying attributes such as
user.emailarrive as expected (external providers need extra work here) - Agreed on a diagnostic path for when nothing arrives (
claude --debug, checking which managed source is active) - Decided the purpose, scope, audience, retention, and deletion process for content logging
- Shipped
OTEL_LOG_ASSISTANT_RESPONSES=0explicitly, if you only want prompts recorded - Confirmed
OTEL_LOG_RAW_API_BODIESis absent from the payload you distribute - Completed employee notification and any required internal process
- Separated estimated cost from authoritative billing in internal reporting
FAQ
Do the OpenTelemetry cost figures match my invoice?
Not necessarily. They're estimates computed from token counts at standard list rates, so contracted discounts and promotional pricing aren't reflected. On Pro, Max, Team, and Enterprise subscriptions, usage inside the seat allowance isn't metered in dollars at all. Your provider's billing console is the system of record.
Is visibility worth it if we're on a subscription?
Yes. The value is less in the dollar figure than in the pattern: who is actually using the tool, which models they use, and how long sessions run. That informs adding or reclaiming seats, spotting members who keep hitting usage limits, and sharing effective workflows internally.
Will managed settings fully prevent configuration changes?
No. Managed settings are a client-side control, and the documentation states that on unmanaged devices they can be bypassed without admin access. Endpoint-managed settings via MDM give stronger guarantees, but you still want telemetry to confirm what machines are actually doing.
Can we see usage without storing prompt content?
Yes. Even with telemetry enabled, every content-logging flag stays off by default. In that state you get metrics and events without message content, which already covers per-user and per-model token counts, estimated cost, session counts, and productivity metrics. Content logging is an additional step for when you have a specific audit requirement.
Does this work through Bedrock or Google Cloud?
Telemetry export itself works, with caveats. Server-managed settings aren't available, so delivery goes through MDM or a gateway; the setup falls outside Anthropic's analytics dashboards; and billing sits with your cloud provider. On top of that, `user.email` may not be attached, so per-user aggregation needs an identifier you supply yourself. Verify in a small pilot that the attributes you need actually arrive.
Start seeing your Claude Code usage today
Aimeterly receives the OpenTelemetry data Claude Code sends once telemetry is enabled, and turns it into usage, estimated cost, and productivity dashboards — plus audit-log search across the content types your organization turns on in its settings. No Collector, no time-series database. Generate the snippet, distribute it, approve it if prompted, restart Claude Code, and watch for claude_code.session.count to arrive.
No credit card required · 14-day Pro trial included