There are four ways to track Claude Code usage across a team, and they answer different questions. /usage shows one developer their own session. The built-in analytics (the claude.ai admin console on Team and Enterprise plans, or the Claude Console on API billing) show adoption and spend per user. OpenTelemetry export streams per-user tokens, cost, sessions, commits, and pull requests into your own observability stack in near real time, on any plan or provider. An LLM gateway records every request with the developer's identity, the model, tokens, and cost, and can also enforce budgets. Most teams end up using built-in analytics for adoption and either OpenTelemetry or a gateway for cost attribution by person, team, and repository.
This post sets up each option, shows how to attribute usage to projects as well as people, and lists the weekly numbers worth reporting.
Pick the right tracking method
| Method | Works on | Per-user | Per-team or project | Real time | Enforces limits |
|---|---|---|---|---|---|
/usage |
Every plan and provider | Own machine only | No | Yes | No |
| Team and Enterprise analytics | Claude for Teams and Enterprise | Yes (spend report CSV, Enterprise Analytics API) | By user groups | Updated daily | Spend limits for usage credits |
| Console dashboard and Claude Code Analytics API | Claude Console (API) | Yes | By workspace | Daily metrics | Workspace spend limits |
| OpenTelemetry export | Every plan and provider | Yes | Yes, via resource attributes | Near real time | No |
| LLM gateway | API keys and cloud providers | Yes, per virtual key | Yes, via key metadata and headers | Per request | Yes: budgets, rate limits, model allowlists |
If your developers use Claude Code through Amazon Bedrock, Google Cloud, or Microsoft Foundry, the built-in analytics do not cover that usage. Claude Code does not send metrics from your cloud back to Anthropic, so OpenTelemetry or a gateway is the only way to get per-developer numbers there, per the Claude Code cost documentation.
Option 1: /usage for individual developers
Every developer can run /usage in a session. The Session block shows token usage by model, cache reads and writes, and a dollar estimate computed locally at list price:
Total cost: $0.55
Total duration (API): 6m 20s
Total duration (wall): 6h 33m 10s
Total code changes: 0 lines added, 0 lines removed
Usage by model:
claude-sonnet-4-6: 1.2k input, 5.3k output, 940.0k cache read, 50.0k cache write ($0.55)
On Pro, Max, Team, and Enterprise plans, /usage also attributes recent usage to skills, subagents, plugins, and individual MCP servers, and recommends changes for anything behind 10% or more of recent usage (for example, trimming a large CLAUDE.md). Press d or w to switch between 24 hours and 7 days.
It is useful for individual habits, and nothing more: the figures come from local session history on that one machine.
Option 2: Built-in analytics
Team and Enterprise plans. The analytics dashboard shows daily active users, sessions, and contribution metrics with CSV export. The spend report in org analytics shows estimated spend per user and per model, updated daily, once usage credits are on. On Enterprise, the Enterprise Analytics API returns per-user usage and cost reports programmatically with a key that has the read:analytics scope.
Claude Console (API billing). The first time someone authenticates Claude Code with a Console account, a workspace called "Claude Code" is created automatically for centralized cost tracking. The Console dashboard shows spend and accepted lines per member, and the Claude Code Analytics API returns the same daily per-user metrics with an Admin API key.
Built-in analytics need no setup, which makes them the right first step. Their limits: daily granularity, no custom dimensions such as repository or ticket, and no coverage for cloud-provider usage.
Option 3: OpenTelemetry export
Claude Code exports metrics and events over OpenTelemetry on every plan and provider. Per the monitoring documentation, you turn it on with environment variables:
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp # otlp, prometheus, console, none
export OTEL_LOGS_EXPORTER=otlp # events: prompts, tool results, API requests
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector.example.com:4317
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer your-token"
The metrics that matter for usage tracking:
| Metric | What it counts |
|---|---|
claude_code.session.count |
CLI sessions started |
claude_code.cost.usage |
Session cost in USD |
claude_code.token.usage |
Tokens, by type: input, output, cacheRead, cacheCreation
|
claude_code.lines_of_code.count |
Lines added or removed |
claude_code.commit.count |
Git commits created |
claude_code.pull_request.count |
Pull requests created |
claude_code.code_edit_tool.decision |
Accept and reject decisions for edits |
claude_code.active_time.total |
Active time, by type: user or cli
|
Every metric carries user.email (when available), user.account_uuid, organization.id, and session.id. Add team and cost-center labels with resource attributes (no spaces in values):
export OTEL_RESOURCE_ATTRIBUTES="department=engineering,team.id=platform,cost_center=eng-123"
Roll it out with managed settings
Developers forget environment variables. Push the configuration to every machine through the managed settings file instead. When managed settings set an OTLP endpoint, protocol, or credential, Claude Code removes conflicting developer-set variables at startup, and repository .claude/settings.json files cannot enable telemetry or redirect it:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_METRICS_EXPORTER": "otlp",
"OTEL_LOGS_EXPORTER": "otlp",
"OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4317",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer example-token"
}
}
Prompt content in the claude_code.user_prompt event is redacted unless you set OTEL_LOG_USER_PROMPTS=1. Leave it off unless your policy allows storing prompts.
Query it in Prometheus
The exact Prometheus metric names depend on how your collector translates OTLP names and units, so run curl -s <your-prometheus-exporter>/metrics | grep claude_code before writing queries. With a common translation, cost per developer per day looks like this:
# Cost per developer over the last day (adjust the metric and label names to your exporter)
sum by (user_email) (increase(claude_code_cost_usage_USD_total[1d]))
# Tokens by type per team
sum by (team_id, type) (increase(claude_code_token_usage_tokens_total[1d]))
Option 4: Route Claude Code through an LLM gateway
A gateway sits between Claude Code and the provider. Every request is logged with the developer's key, model, tokens, cost, and latency, and the same key carries budgets and rate limits. OpenTelemetry tells you what happened; a gateway can also stop it from happening.
With Bifrost, an open-source AI gateway, each developer gets a virtual key whose metadata (owner, team, cost center) is copied onto every log entry and cannot be overridden by the caller:
curl -s -u "$BF_ADMIN:$BF_PASS" -X POST https://bifrost.internal.example.com/api/governance/virtual-keys \
-H "Content-Type: application/json" \
-d '{
"name": "dev-alice",
"team_id": "<platform-team-id>",
"metadata": {"owner": "alice@example.com", "team": "platform", "cost_center": "cc-1234"},
"provider_configs": [{"provider": "anthropic", "allowed_models": ["claude-sonnet-4-6"], "key_ids": ["*"], "weight": 1.0}],
"budgets": [{"max_limit": 20.00, "reset_duration": "1d"}, {"max_limit": 300.00, "reset_duration": "1M"}],
"is_active": true
}'
Point Claude Code at it in ~/.claude/settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "https://bifrost.internal.example.com/anthropic",
"ANTHROPIC_AUTH_TOKEN": "sk-bf-your-virtual-key"
}
}
If developers keep their Claude subscription login, send the virtual key as a header instead, so the gateway still logs and budgets their traffic: "ANTHROPIC_CUSTOM_HEADERS": "x-bf-vk: sk-bf-your-virtual-key", without setting ANTHROPIC_AUTH_TOKEN.
Then query spend by person or cost center from the log API, or from Prometheus:
curl -s -u "$BF_ADMIN:$BF_PASS" "https://bifrost.internal.example.com/api/logs?metadata_cost_center=cc-1234" | jq '.'
sum by (virtual_key_name) (increase(bifrost_cost_total[1d]))
sum by (team_name) (increase(bifrost_cost_total[7d]))
Track usage per project, not only per person
Per-person numbers answer "who"; finance and engineering leads also ask "which repository" and "which pipeline." Two ways to add that dimension:
Per-request headers through the gateway. Bifrost reads x-bf-dim-<name> headers and passes the value to logs, OpenTelemetry spans, and Prometheus labels. Claude Code can send custom headers, so set a repository dimension in that repository's settings (a header with no secret in it is safe to commit):
{
"env": {
"ANTHROPIC_CUSTOM_HEADERS": "x-bf-dim-repo: payments-api"
}
}
If you already use ANTHROPIC_CUSTOM_HEADERS for the x-bf-vk header, put both headers in the same value on separate lines, because a project-level value replaces the user-level one.
Separate keys for CI. Give every pipeline its own virtual key with metadata naming the repo and workflow, a small daily budget, and an expires_at for one-off jobs. CI spend then never mixes with interactive use.
The weekly report worth sending
Raw dashboards get ignored. A short weekly summary per team, built from gateway logs or OpenTelemetry plus your VCS, gets read:
- Adoption: active developers per week, sessions per developer, and the share of developers above a minimal-use threshold.
- Spend: cost per active developer per week and the top 10 spenders. A top spender is usually a misconfigured loop or the wrong default model, not a power user.
- Model mix: share of requests per model. Push routine work to cheaper models with agent aliases.
- Value: PR cycle time, review rework, and revert rate for agent-assisted PRs against your pre-rollout baseline. Tag agent-assisted PRs with a commit trailer or label so you can join them.
- Friction: budget rejections and model-not-allowed errors. Rising counts mean limits or allowlists need adjusting.
Review per-developer budgets after the first two weeks and set them around the 90th percentile of observed daily spend.
Install the skills behind this post
ai-coding-agent-governance sets up per-developer keys, budgets, managed settings, CI keys, and adoption metrics for Claude Code, Codex CLI, Gemini CLI, Cursor, GitHub Copilot, and OpenCode.
- GitHub: github.com/build-with-ai-hq/ai-coding-agent-governance
- skills.sh: skills.sh/build-with-ai-hq/ai-coding-agent-governance
npx skills add build-with-ai-hq/ai-coding-agent-governance
llm-observability-stack builds the dashboards and alerts: cost per user and feature, TTFT, error classification, and agent traces with OpenTelemetry GenAI conventions.
- GitHub: github.com/build-with-ai-hq/llm-observability-stack
- skills.sh: skills.sh/build-with-ai-hq/llm-observability-stack
npx skills add build-with-ai-hq/llm-observability-stack
Ask your agent "how do we see Claude Code usage per developer and per team?" and it starts with an audit of raw provider keys, agent configs, and managed policy on the machine, then writes the configuration for the path you choose.
Related reading
- How Much Does Claude Code Cost for a Team? Real Numbers and Per-Developer Budgets
- LLM Observability: What to Track in Production (Tokens, Cost, Latency, TTFT and Agent Traces)
FAQ
Can I see Claude Code usage per developer on a Team plan?
Yes. The spend report in org analytics lists token usage and estimated spend per user and per model, with CSV export. The analytics dashboard shows active users and sessions.
Does Claude Code send usage data to Anthropic when I use Bedrock or Vertex?
No metrics from your cloud usage go back to Anthropic, so Anthropic's analytics do not cover it. Use OpenTelemetry export or a gateway for per-developer numbers.
Is OpenTelemetry export on by default?
No. Set CLAUDE_CODE_ENABLE_TELEMETRY=1 and choose an exporter. Use managed settings to enforce it across machines.
Can I track Claude Code usage per repository?
Yes. Send a repository dimension header through a gateway (for example x-bf-dim-repo with Bifrost), or give each CI pipeline its own key with repository metadata.
How do I make reported costs match our contract price?
Set the modelPricing managed setting to your contracted per-token rates. It changes what Claude Code reports in /usage, the status line, and OpenTelemetry, not what you are charged.




Top comments (0)