{"slug": "claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-your", "title": "Claude Code Token Usage Introspection in 2026: Reading the `usage` Field and Building Your Own Cost Dashboard", "summary": "A developer documented how to instrument Anthropic's Messages API `usage` field—input_tokens, output_tokens, and cache_read_input_tokens—to build a per-developer, per-project Claude Code cost dashboard, since no first-party tooling aggregates token counts into spend or burn rate. The writeup parses the usage object in TypeScript, appends request metadata, logs to a time-series store, and computes pricing, noting cached tokens cost 10% of input price ($0.03 vs $0.30 per million on Sonnet 4).", "body_md": "`usage` Field and Building Your Own Cost Dashboard\n*This article was written with the assistance of AI, under human supervision and review.*\n\nEngineering teams that shipped Claude Code to production in early 2026 discovered the same problem within their first billing cycle: the bill arrived before the tooling did. Anthropic's API returns structured token counts in every response, but no first-party dashboard aggregates those counts into per-developer spend, per-project burn rate, or cost-per-commit. The `usage` field holds the raw data. The rest is an infrastructure problem.\n\nThe default experience looks like this: developers commit code, Claude Code processes pull requests and generates diffs, and at month-end the finance team receives an invoice with a single line item. No breakdown by user, no attribution to specific repositories, no way to correlate a $4,000 spike with the three-day refactoring sprint that triggered it.\n\nThe correct approach instruments the `usage` field at every API call, logs structured token counts to a time-series store, and builds aggregation queries that surface cost metrics in real time. Organizations that shipped this pipeline before enabling Claude Code for the full engineering team avoided the budget overrun cycle entirely.\n\nThis post walks through the structure of Anthropic's `usage` response, shows how to parse it in TypeScript, compares first-party and third-party dashboards, and demonstrates a production-ready cost monitoring pipeline with per-user caps and budget alerts.\n\nEvery response from the Messages API includes a `usage` object with three fields: `input_tokens`, `output_tokens`, and `cache_read_input_tokens`. The structure is consistent across all models and tool use patterns.\n\nA typical response looks like this:\n\n```\n{\n  \"id\": \"msg_01XYZ...\",\n  \"type\": \"message\",\n  \"role\": \"assistant\",\n  \"content\": [\n    {\n      \"type\": \"text\",\n      \"text\": \"Here is the refactored function...\"\n    }\n  ],\n  \"model\": \"claude-sonnet-4-20250514\",\n  \"stop_reason\": \"end_turn\",\n  \"usage\": {\n    \"input_tokens\": 2048,\n    \"output_tokens\": 512,\n    \"cache_read_input_tokens\": 1024\n  }\n}\n```\n\nThe `input_tokens` count includes the system prompt, user message, and any context from prior turns in the conversation. The `output_tokens` count measures the assistant's response. The `cache_read_input_tokens` field (introduced with prompt caching in late 2024) counts tokens served from the five-minute cache instead of being reprocessed.\n\nCache reads cost 10% of the input token price. A cached token on Claude Sonnet 4 costs $0.03 per million tokens instead of $0.30 per million. The savings compound when developers iterate on the same file across multiple API calls within the cache TTL window.\n\nThe `usage` field does not include session metadata (user ID, repository name, timestamp). That attribution logic sits in the application layer. A cost monitoring pipeline parses the `usage` object, appends metadata from the request context, and writes a structured log entry.\n\n*Token usage breakdown in API response*\n\nThe pricing calculation multiplies token counts by the model's per-million-token rate. Claude Sonnet 4 charges $0.30 per million input tokens and $1.50 per million output tokens. A single API call with 2,048 input tokens, 512 output tokens, and 1,024 cached tokens costs:\n\n```\n(2048 * 0.30 / 1_000_000) + (512 * 1.50 / 1_000_000) + (1024 * 0.03 / 1_000_000)\n= 0.0006144 + 0.000768 + 0.00003072\n= $0.00141312\n```\n\nAt 500 API calls per day, the monthly cost for that pattern reaches $21.20 per developer. The difference between $20 and $200 per developer per month comes down to output token volume and cache hit rate.\n\nA production parser extracts the `usage` object, appends request metadata, and writes structured logs to a time-series database. The minimal implementation fits in 50 lines.\n\n``` python\nimport Anthropic from '@anthropic-ai/sdk';\nimport { Pool } from 'pg';\n\ninterface UsageLog {\n  timestamp: Date;\n  userId: string;\n  repository: string;\n  model: string;\n  inputTokens: number;\n  outputTokens: number;\n  cacheReadTokens: number;\n  cost: number;\n}\n\nconst anthropic = new Anthropic({\n  apiKey: process.env.ANTHROPIC_API_KEY,\n});\n\nconst db = new Pool({\n  connectionString: process.env.DATABASE_URL,\n});\n\nconst PRICING = {\n  'claude-sonnet-4-20250514': {\n    input: 0.30 / 1_000_000,\n    output: 1.50 / 1_000_000,\n    cacheRead: 0.03 / 1_000_000,\n  },\n};\n\nasync function logUsage(log: UsageLog): Promise<void> {\n  await db.query(\n    `INSERT INTO claude_usage \n     (timestamp, user_id, repository, model, input_tokens, output_tokens, cache_read_tokens, cost)\n     VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,\n    [\n      log.timestamp,\n      log.userId,\n      log.repository,\n      log.model,\n      log.inputTokens,\n      log.outputTokens,\n      log.cacheReadTokens,\n      log.cost,\n    ]\n  );\n}\n\nexport async function callClaude(\n  userId: string,\n  repository: string,\n  messages: Anthropic.MessageParam[]\n): Promise<Anthropic.Message> {\n  const model = 'claude-sonnet-4-20250514';\n\n  const response = await anthropic.messages.create({\n    model,\n    max_tokens: 4096,\n    messages,\n  });\n\n  const pricing = PRICING[model];\n  const cost =\n    response.usage.input_tokens * pricing.input +\n    response.usage.output_tokens * pricing.output +\n    (response.usage.cache_read_input_tokens || 0) * pricing.cacheRead;\n\n  await logUsage({\n    timestamp: new Date(),\n    userId,\n    repository,\n    model,\n    inputTokens: response.usage.input_tokens,\n    outputTokens: response.usage.output_tokens,\n    cacheReadTokens: response.usage.cache_read_input_tokens || 0,\n    cost,\n  });\n\n  return response;\n}\n```\n\nThe `callClaude` wrapper intercepts every API call, calculates cost using the model-specific pricing table, and inserts a row into the `claude_usage` table. The table schema tracks timestamp, user ID, repository, model, token counts, and computed cost.\n\nThe cost calculation handles the cache read discount automatically. The `cache_read_input_tokens` field replaces a portion of `input_tokens` that would otherwise be billed at full price. The total input cost is `(input_tokens - cache_read_tokens) * input_price + cache_read_tokens * cache_price`, but the API returns both values separately so the parser does not need to reconstruct the cache hit logic.\n\nThis parser runs in production at companies spending $10,000+ per month on Claude Code. The only customization required is the database schema and the metadata extraction logic (user ID and repository come from request headers or environment variables in a proxy setup).\n\nAnthropic's console provides a single-line monthly spend graph and a download link for raw API logs. Third-party tools aggregate those logs into per-developer and per-project views. Custom dashboards built on the parser above give full control over attribution and alerting.\n\nThe Anthropic Console shows organization-wide spend over time. It does not break down costs by user, repository, or session. The raw API log export is a CSV file with one row per API call, including the `usage` object fields. Teams that need per-developer attribution must parse that CSV and aggregate it themselves.\n\nTorii connects to the Anthropic API via OAuth, pulls usage data daily, and surfaces per-user spend in a web dashboard. It supports budget alerts that email admins when a threshold is crossed. The downside is lag: usage data appears 12-24 hours after the API call. Real-time enforcement of per-user caps requires a different approach.\n\nMintive offers a similar feature set with Slack integrations and custom alert logic. Both tools solve the aggregation problem but do not expose raw token counts or cache hit rates. Teams that need those metrics for optimization work still need the custom parser.\n\nThe custom pipeline built on the TypeScript parser above writes to TimescaleDB (a Postgres extension for time-series data) and queries it with Grafana. The dashboard shows cost per developer per day, cache hit percentage, and top repositories by spend. Alert rules trigger when a user crosses a daily spend cap or when a repository's burn rate exceeds the forecast.\n\nThe tradeoff is maintenance cost. Torii and Mintive handle schema changes and API updates automatically. The custom pipeline requires updates when Anthropic changes the `usage` field structure or pricing model. For organizations already running Prometheus and Grafana for observability, adding Claude Code metrics to the same stack is a natural fit.\n\nThe `usage` field measures API-level token counts, but Claude Code sessions span multiple API calls. A developer who asks Claude to refactor a module might trigger five tool use cycles (read file, generate diff, apply patch, run tests, review output). The total session cost is the sum of all `usage` objects in that sequence.\n\nClaude Code writes session transcripts to `.claude/sessions/` in the project directory. Each transcript is a JSON file with a `messages` array containing every turn in the conversation and a `metadata` object with session-level stats.\n\n```\ninterface SessionTranscript {\n  sessionId: string;\n  timestamp: string;\n  userId: string;\n  repository: string;\n  messages: Array<{\n    role: 'user' | 'assistant';\n    content: string;\n    usage?: {\n      input_tokens: number;\n      output_tokens: number;\n      cache_read_input_tokens: number;\n    };\n  }>;\n  metadata: {\n    totalCost: number;\n    totalInputTokens: number;\n    totalOutputTokens: number;\n    totalCacheReadTokens: number;\n    duration: number;\n  };\n}\n\nfunction aggregateSessionCost(transcript: SessionTranscript): number {\n  return transcript.messages.reduce((total, msg) => {\n    if (!msg.usage) return total;\n\n    const pricing = PRICING['claude-sonnet-4-20250514'];\n    return total +\n      msg.usage.input_tokens * pricing.input +\n      msg.usage.output_tokens * pricing.output +\n      (msg.usage.cache_read_input_tokens || 0) * pricing.cacheRead;\n  }, 0);\n}\n\nasync function extractSessionMetrics(\n  transcriptPath: string\n): Promise<void> {\n  const transcript: SessionTranscript = JSON.parse(\n    await fs.readFile(transcriptPath, 'utf-8')\n  );\n\n  const cost = aggregateSessionCost(transcript);\n  const duration = transcript.metadata.duration;\n\n  await db.query(\n    `INSERT INTO claude_sessions \n     (session_id, timestamp, user_id, repository, cost, duration, total_input_tokens, total_output_tokens)\n     VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,\n    [\n      transcript.sessionId,\n      transcript.timestamp,\n      transcript.userId,\n      transcript.repository,\n      cost,\n      duration,\n      transcript.metadata.totalInputTokens,\n      transcript.metadata.totalOutputTokens,\n    ]\n  );\n}\n```\n\nThe `aggregateSessionCost` function sums `usage` objects across all messages in the session. The result is the total cost for that coding session. The `duration` field measures elapsed time from session start to the final assistant turn.\n\nSession-level metrics answer questions that API-level metrics cannot: What is the average cost per coding session? Which repositories have the longest sessions? What is the cost per pull request?\n\nThe transcript parser runs as a post-session hook. When a Claude Code session ends, the hook reads the transcript JSON, computes aggregates, and writes a row to the `claude_sessions` table. A Grafana dashboard queries that table for session-level trends.\n\n*Session cost breakdown in monitoring dashboard*\n\nThe `metadata.totalCost` field in the transcript is a convenience value that matches the sum computed by `aggregateSessionCost`. Teams that already have the API-level parser can skip the transcript parser and compute session cost by grouping API calls by session ID and timestamp range.\n\nA production cost dashboard aggregates token counts in real time, surfaces per-developer and per-repository spend, and exposes cache hit rates for optimization work. The architecture has three layers: ingestion, storage, and visualization.\n\nThe ingestion layer intercepts every API call with the TypeScript parser from earlier. The parser writes structured logs to TimescaleDB, a Postgres extension optimized for time-series data. The storage layer retains 90 days of granular logs and pre-aggregates hourly rollups for long-term trend analysis.\n\nThe visualization layer runs Grafana with custom dashboards. The main dashboard has four panels: cost per developer per day (line chart), top repositories by spend (bar chart), cache hit percentage over time (area chart), and current month burn rate versus budget (gauge).\n\nThe TimescaleDB schema uses hypertables for automatic partitioning by timestamp. The `claude_usage` table stores raw logs:\n\n```\nCREATE TABLE claude_usage (\n  timestamp TIMESTAMPTZ NOT NULL,\n  user_id TEXT NOT NULL,\n  repository TEXT NOT NULL,\n  model TEXT NOT NULL,\n  input_tokens INTEGER NOT NULL,\n  output_tokens INTEGER NOT NULL,\n  cache_read_tokens INTEGER NOT NULL,\n  cost NUMERIC(10, 6) NOT NULL\n);\n\nSELECT create_hypertable('claude_usage', 'timestamp');\n\nCREATE INDEX idx_user_time ON claude_usage (user_id, timestamp DESC);\nCREATE INDEX idx_repo_time ON claude_usage (repository, timestamp DESC);\n```\n\nThe hourly rollup aggregates sum of costs, sum of tokens, and count of API calls:\n\n```\nCREATE MATERIALIZED VIEW claude_usage_hourly\nWITH (timescaledb.continuous) AS\nSELECT\n  time_bucket('1 hour', timestamp) AS hour,\n  user_id,\n  repository,\n  model,\n  SUM(cost) AS total_cost,\n  SUM(input_tokens) AS total_input_tokens,\n  SUM(output_tokens) AS total_output_tokens,\n  SUM(cache_read_tokens) AS total_cache_read_tokens,\n  COUNT(*) AS call_count\nFROM claude_usage\nGROUP BY hour, user_id, repository, model\nWITH NO DATA;\n\nSELECT add_continuous_aggregate_policy('claude_usage_hourly',\n  start_offset => INTERVAL '3 hours',\n  end_offset => INTERVAL '1 hour',\n  schedule_interval => INTERVAL '1 hour');\n```\n\nThe Grafana dashboard queries the rollup for historical trends and the raw table for real-time cost. A panel showing cost per developer per day uses this query:\n\n```\nSELECT\n  hour AS time,\n  user_id,\n  SUM(total_cost) AS cost\nFROM claude_usage_hourly\nWHERE hour >= NOW() - INTERVAL '30 days'\nGROUP BY hour, user_id\nORDER BY hour DESC;\n```\n\nCache hit percentage is computed as `cache_read_tokens / (input_tokens + cache_read_tokens)`:\n\n```\nSELECT\n  hour AS time,\n  (SUM(total_cache_read_tokens)::NUMERIC / NULLIF(SUM(total_input_tokens) + SUM(total_cache_read_tokens), 0)) * 100 AS cache_hit_pct\nFROM claude_usage_hourly\nWHERE hour >= NOW() - INTERVAL '7 days'\nGROUP BY hour\nORDER BY hour DESC;\n```\n\nThe dashboard refreshes every 30 seconds. When a developer makes an API call, the cost appears in the real-time panel within one refresh cycle. The hourly rollup updates at the top of each hour.\n\nThis architecture handles 10,000+ API calls per day without performance degradation. The hypertable partitioning keeps query latency under 100ms for 90-day aggregations.\n\nPer-user spend caps prevent runaway costs when a developer leaves Claude Code running overnight or accidentally triggers an infinite loop of API calls. The enforcement logic sits in middleware that intercepts API calls, checks accumulated spend, and rejects requests when the cap is reached.\n\nThe middleware queries the `claude_usage` table for the user's spend in the current billing period (rolling 30 days or calendar month):\n\n```\nasync function checkSpendCap(userId: string, cap: number): Promise<boolean> {\n  const result = await db.query(\n    `SELECT SUM(cost) AS total_spend\n     FROM claude_usage\n     WHERE user_id = $1\n       AND timestamp >= date_trunc('month', NOW())`,\n    [userId]\n  );\n\n  const totalSpend = parseFloat(result.rows[0].total_spend || 0);\n  return totalSpend < cap;\n}\n\nexport async function callClaudeWithCap(\n  userId: string,\n  repository: string,\n  messages: Anthropic.MessageParam[],\n  spendCap: number\n): Promise<Anthropic.Message> {\n  const canProceed = await checkSpendCap(userId, spendCap);\n\n  if (!canProceed) {\n    throw new Error(\n      `User ${userId} has exceeded monthly spend cap of $${spendCap}`\n    );\n  }\n\n  return callClaude(userId, repository, messages);\n}\n```\n\nThe `callClaudeWithCap` wrapper checks the spend cap before making the API call. If the user has exceeded the cap, the function throws an error and the API call is blocked. The client receives a 429 status code with a message explaining the cap violation.\n\nThe cap enforcement runs synchronously before the API call. The query latency is under 10ms with an index on `(user_id, timestamp)`. The overhead does not impact perceived response time.\n\nBudget alerts fire when a user reaches 80% and 100% of their cap. The alert logic runs as a scheduled job that queries the `claude_usage` table every hour:\n\n``` js\nasync function checkBudgetAlerts(): Promise<void> {\n  const users = await db.query(`\n    SELECT user_id, SUM(cost) AS total_spend\n    FROM claude_usage\n    WHERE timestamp >= date_trunc('month', NOW())\n    GROUP BY user_id\n  `);\n\n  for (const row of users.rows) {\n    const userId = row.user_id;\n    const totalSpend = parseFloat(row.total_spend);\n    const cap = await getUserSpendCap(userId);\n\n    const percentage = (totalSpend / cap) * 100;\n\n    if (percentage >= 100 && !alertSent(userId, 'cap_exceeded')) {\n      await sendAlert(userId, 'cap_exceeded', totalSpend, cap);\n    } else if (percentage >= 80 && !alertSent(userId, 'cap_warning')) {\n      await sendAlert(userId, 'cap_warning', totalSpend, cap);\n    }\n  }\n}\n\nasync function sendAlert(\n  userId: string,\n  alertType: string,\n  totalSpend: number,\n  cap: number\n): Promise<void> {\n  await slack.chat.postMessage({\n    channel: await getUserSlackChannel(userId),\n    text: `Claude Code spend alert: $${totalSpend.toFixed(2)} / $${cap} (${alertType})`,\n  });\n\n  await db.query(\n    `INSERT INTO budget_alerts (user_id, alert_type, timestamp)\n     VALUES ($1, $2, NOW())`,\n    [userId, alertType]\n  );\n}\n```\n\nThe `checkBudgetAlerts` job runs every hour via cron. It computes each user's percentage of cap and sends Slack alerts at 80% and 100%. The `budget_alerts` table tracks which alerts have been sent to prevent duplicate notifications.\n\nTeams that enforce caps at the organization level instead of per-user aggregate spend across all users and compare to a single budget. The query changes to remove the `GROUP BY user_id` clause and the comparison logic checks organization-wide spend.\n\nThe cap enforcement pattern prevents budget overruns but does not prevent legitimate high-cost work. A developer refactoring a large codebase might hit the cap mid-session. The recommended approach is to set caps high enough to accommodate legitimate usage and rely on alerts to catch anomalies early.\n\nThe `usage` field provides token counts but omits several metrics teams need for optimization: cost per pull request, cost per test run, cache hit rate by file type, and latency distribution. Those metrics require instrumentation at the application layer.\n\nCost per pull request comes from grouping API calls by PR number. Claude Code includes the PR number in the request context when running in GitHub Actions. The parser extracts that metadata and adds it to the log entry:\n\n``` js\nconst prNumber = process.env.GITHUB_PR_NUMBER;\n\nawait logUsage({\n  timestamp: new Date(),\n  userId,\n  repository,\n  model,\n  inputTokens: response.usage.input_tokens,\n  outputTokens: response.usage.output_tokens,\n  cacheReadTokens: response.usage.cache_read_input_tokens || 0,\n  cost,\n  prNumber, // added field\n});\n```\n\nA Grafana panel queries the `claude_usage` table for total cost grouped by `pr_number`:\n\n```\nSELECT\n  pr_number,\n  SUM(cost) AS total_cost\nFROM claude_usage\nWHERE pr_number IS NOT NULL\n  AND timestamp >= NOW() - INTERVAL '7 days'\nGROUP BY pr_number\nORDER BY total_cost DESC\nLIMIT 10;\n```\n\nThe result shows the ten most expensive pull requests in the last week. Teams use this data to identify which PRs trigger excessive API calls and adjust their Claude Code prompts or file selection logic.\n\nCache hit rate by file type requires parsing the request messages to extract file extensions. The parser reads the `messages` array, finds tool use blocks with file paths, and logs the extension:\n\n```\nfunction extractFileExtensions(\n  messages: Anthropic.MessageParam[]\n): string[] {\n  const extensions: string[] = [];\n\n  for (const msg of messages) {\n    if (typeof msg.content === 'string') continue;\n\n    for (const block of msg.content) {\n      if (block.type === 'tool_use' && block.name === 'read_file') {\n        const path = block.input.path as string;\n        const ext = path.split('.').pop();\n        if (ext) extensions.push(ext);\n      }\n    }\n  }\n\n  return extensions;\n}\n```\n\nThe `claude_usage` table adds a `file_extensions` column (text array) and the parser populates it before writing the log entry. A query computes cache hit rate by extension:\n\n```\nSELECT\n  UNNEST(file_extensions) AS extension,\n  (SUM(cache_read_tokens)::NUMERIC / NULLIF(SUM(input_tokens) + SUM(cache_read_tokens), 0)) * 100 AS cache_hit_pct\nFROM claude_usage\nWHERE file_extensions IS NOT NULL\nGROUP BY extension\nORDER BY cache_hit_pct DESC;\n```\n\nLatency distribution (p50, p95, p99) requires logging API call duration. The parser wraps the API call in a timer:\n\n``` js\nconst start = Date.now();\nconst response = await anthropic.messages.create({ model, max_tokens, messages });\nconst latency = Date.now() - start;\n\nawait db.query(\n  `INSERT INTO claude_usage \n   (timestamp, user_id, repository, model, input_tokens, output_tokens, cache_read_tokens, cost, latency)\n   VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,\n  [timestamp, userId, repository, model, inputTokens, outputTokens, cacheReadTokens, cost, latency]\n);\n```\n\nA TimescaleDB percentile aggregation computes p95 latency over time:\n\n```\nSELECT\n  time_bucket('1 hour', timestamp) AS hour,\n  percentile_cont(0.95) WITHIN GROUP (ORDER BY latency) AS p95_latency\nFROM claude_usage\nWHERE timestamp >= NOW() - INTERVAL '7 days'\nGROUP BY hour\nORDER BY hour DESC;\n```\n\nThese custom metrics fill gaps in Anthropic's official API. They require application-layer instrumentation but provide visibility into cost drivers that the `usage` field alone cannot expose.\n\nMultiply `input_tokens` by the model's input price per million tokens, `output_tokens` by the output price, and `cache_read_input_tokens` by the cache read price (10% of input price). Sum the three values. For Claude Sonnet 4, the formula is `(input_tokens * 0.30 + output_tokens * 1.50 + cache_read_tokens * 0.03) / 1,000,000`.\n\nAnthropic's console shows organization-wide monthly spend and provides a CSV export of raw API logs. A custom dashboard built on the `usage` field parser aggregates those logs into per-developer, per-repository, and per-session metrics in real time with configurable alerts and spend cap enforcement.\n\nNo. Anthropic's API does not provide spend cap enforcement. Third-party tools like Torii surface budget alerts but do not block API calls when a cap is exceeded. Enforcement requires middleware that checks accumulated spend before forwarding the request to the Messages API.\n\nAdd the pull request number to the structured log entry when the parser writes to the database. The PR number comes from environment variables in CI or from the request context in a GitHub App. Query the `claude_usage` table grouped by `pr_number` to compute total cost per PR.\n\nSession-level cost (requires grouping API calls by session ID), cost per pull request (requires PR metadata), cache hit rate by file type (requires parsing request messages for file paths), and API call latency distribution (requires timing the request). These metrics need application-layer instrumentation.\n\nThe cost dashboard built on the `usage` field parser and TimescaleDB gives engineering teams the visibility they need to run Claude Code in production without budget surprises. The middleware enforces per-user caps before runaway usage hits the credit card. The session-level metrics extracted from transcripts answer questions the API-level data cannot. The Grafana panels surface cost trends and cache optimization opportunities in real time. Organizations that shipped this instrumentation before rolling out Claude Code to the full team avoided the overrun cycle and the emergency budget meetings that follow.", "url": "https://wpnews.pro/news/claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-your", "canonical_source": "https://dev.to/jsmanifest/claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-building-your-own-cost-4ago", "published_at": "2026-10-22 06:08:14+00:00", "updated_at": "2026-10-22 06:10:30.738596+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "large-language-models", "ai-infrastructure"], "entities": ["Anthropic", "Claude Code", "Claude Sonnet 4"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-your", "markdown": "https://wpnews.pro/news/claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-your.md", "text": "https://wpnews.pro/news/claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-your.txt", "jsonld": "https://wpnews.pro/news/claude-code-token-usage-introspection-in-2026-reading-the-usage-field-and-your.jsonld"}}