Claude Code JSONL Logs: Measure Token Usage Safely

Claude Code JSONL Logs: Measure Token Usage Safely

Aident AI

Layered indigo records pass through a clear lens into four measured streams, with one incomplete stream stopping before a gold verification sphere.

Claude Code JSONL Logs: Measure Token Usage Safely

Claude Code stores local session transcripts as JSONL files under its project data directory. Those files can help you find relative usage hotspots, repeated messages, and expensive session patterns. They are not an authoritative bill.

The safe workflow is:

  1. Capture Claude Code's /usage view.

  2. Locate the relevant JSONL file without printing the transcript.

  3. Deduplicate repeated assistant messages before adding token fields.

  4. Treat local totals as diagnostic estimates.

  5. Use the Claude Console for authoritative API billing.

Do not upload a raw session log to a public analyzer. Claude Code transcripts can contain prompts, model output, source code, file contents, and tool results.

What each usage source can tell you

Source

Useful for

Do not treat it as

Claude Code /usage

Current-session tokens, local estimates, plan bars, and recent activity

A complete cross-device history or final invoice

Local JSONL logs

Comparing sessions, models, cache fields, and repeated message records

Guaranteed final token counts for every streaming event

ccusage

Aggregating local coding-agent history into daily or session reports

Independent billing truth

Claude Console

Authoritative API usage and billing

A transcript-level explanation of every local workflow choice

Anthropic says /usage computes its cost figure locally and that its recent breakdown is approximate and based on session history on the current machine. Subscription users should read the plan bars rather than interpreting the local dollar estimate as their bill.

Prerequisites

You need:

  • A current Claude Code installation.

  • jq for the manual inspection commands.

  • Read access to your Claude Code data directory.

  • A private terminal where paths and output will not be copied into tickets or chat.

If you set CLAUDE_CONFIG_DIR, use that directory. Otherwise, Claude Code normally stores local project transcripts under ~/.claude/projects/.

Step 1: Record the official in-session view

In the Claude Code session you want to investigate, run:

/usage

Record the session total, model breakdown, cache read and cache creation fields, and whether the screen says it is showing last-known usage. Also note the date, Claude Code version, sign-in method, and whether subagents or agent teams were active.

Expected result: /usage shows the current session's token breakdown. On supported subscription plans, it also shows recent plan usage and activity. If the command says its usage bars are cached, refresh them before making a comparison.

Step 2: Find the session file without dumping it

On macOS or Linux:

claude_root="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"

find "$claude_root/projects" -type f -name '*.jsonl' -print

On PowerShell:

$claudeRoot = if ($env:CLAUDE_CONFIG_DIR) {
  $env:CLAUDE_CONFIG_DIR
} else {
  Join-Path $HOME ".claude"
}

Get-ChildItem (Join-Path $claudeRoot "projects") -Recurse -Filter *.jsonl |
  Sort-Object LastWriteTime -Descending |
  Select-Object LastWriteTime, Length, FullName

Match the path and modification time to the project and session you just measured. Do not use cat on the whole file. A JSONL transcript can be hundreds of megabytes and may contain sensitive content.

Expected result: you see one or more .jsonl paths beneath the configured Claude Code project directory. Copy the exact path for the session you want to inspect.

Step 3: Inspect usage keys, not transcript values

Set a variable to the chosen file:

session_file="/absolute/path/to/session.jsonl"

Then inspect only the usage field names from a small sample:

head -n 100 "$session_file" |
  jq -r 'select(.message.usage?) | .message.usage | keys_unsorted[]' |
  sort -u

A typical result includes fields such as:

cache_creation_input_tokens
cache_read_input_tokens
input_tokens
output_tokens

If nothing appears, the first 100 lines may not contain an assistant usage record. Increase the sample gradually. Do not paste arbitrary transcript lines into an online JSON viewer.

Step 4: Deduplicate before adding token fields

One assistant message can appear on multiple JSONL lines. Adding every usage object can count the same message more than once. The following local command keeps one record per message.id before calculating a session summary:

jq -s '
  [
    .[]
    | select(.message.id? and .message.usage?)
    | { id: .message.id, usage: .message.usage }
  ]
  | unique_by(.id)
  | {
      messages: length,
      input_tokens: (map(.usage.input_tokens // 0) | add // 0),
      output_tokens: (map(.usage.output_tokens // 0) | add // 0),
      cache_read_input_tokens: (
        map(.usage.cache_read_input_tokens // 0) | add // 0
      ),
      cache_creation_input_tokens: (
        map(.usage.cache_creation_input_tokens // 0) | add // 0
      )
    }
' "$session_file"

Expected result: one JSON object with a deduplicated message count and four token categories.

This command is intentionally narrow. It does not calculate dollars, merge multiple machines, or claim that every stored streaming value is final. Claude Code's private log shape can change, so first verify that message.id and message.usage exist in your version.

Step 5: Use an aggregator without granting log access

If you want daily or per-session grouping, run a local tool against the same files. As of July 31, 2026, ccusage 20.0.19 supports Claude Code reports:

pnpm dlx ccusage@20.0.19 claude daily --last 7
pnpm dlx ccusage@20.0.19 claude session --json

The package runs on your machine and reads local coding-agent data. Review the package and its permissions before running it in a sensitive environment. Pinning the version makes the command reproducible; review newer releases before changing that pin.

Compare the aggregator with your manual deduplicated summary. A large difference is a reason to inspect record selection and schema assumptions, not to choose the larger number automatically.

Step 6: Test a before-and-after hypothesis

Raw totals are most useful when you change one thing at a time. For example:

  1. Start a fresh session in a fixed repository state.

  2. Record /usage before the task.

  3. Run one repeatable, read-only task.

  4. Record /usage after the task.

  5. Summarize the matching JSONL file locally.

  6. Repeat after disabling one unused MCP server or shortening one oversized rule file.

Keep the model, effort, repository revision, prompt, and task constant. Compare input, output, cache read, cache creation, and wall time separately. Do not turn one run into a universal savings claim.

For the live-session investigation that comes before this deeper audit, use the Claude Code usage-spike checklist. If tool definitions dominate context, follow the MCP token-usage guide. If a session is missing rather than expensive, use the Claude Code session-recovery guide.

Common failure modes

The JSONL total is much lower than /usage

Do not multiply it by a guessed correction factor. A public ccusage issue documented placeholder or incomplete input_tokens and output_tokens in some Claude Code JSONL streaming records. The issue's measurements are not a guarantee about your version, but they are enough to rule out treating raw sums as billing truth.

Check for missing final records, a different data root, cleaned-up history, subagent transcripts, and usage from another machine. Use the Console for billing decisions.

The total is roughly doubled

Inspect repeated message.id values:

jq -r 'select(.message.id?) | .message.id' "$session_file" |
  sort |
  uniq -c |
  sort -nr |
  head

If the same ID appears more than once, deduplicate before summing. Do not delete the repeated lines from the transcript.

Cache tokens dwarf input and output

Keep cache creation and cache read in separate columns. They have different pricing and represent different work. A total called simply tokens hides that distinction and can make a cache-heavy session look misleadingly expensive.

No JSONL files appear

Confirm CLAUDE_CONFIG_DIR, the project path, and the local retention setting. Anthropic documents a default 30-day local transcript cache, configurable with cleanupPeriodDays. A session created on another device will not appear in this machine's local history.

You are about to share the file

Stop and extract only the minimal aggregate needed. Local Claude Code transcripts are plaintext and can include conversation content and tool output. Remove project names and absolute paths from screenshots. Never publish a raw log to prove a token count.

Why this workflow works

The sequence separates four questions that are easy to blur together:

  • /usage answers what Claude Code currently reports.

  • JSONL inspection explains the local session structure.

  • Deduplication prevents one common counting error.

  • The Claude Console answers what an API account was billed.

That separation lets you diagnose relative changes without claiming false precision. It also preserves the transcript as evidence instead of editing or normalizing the original file.

Audit external Action usage separately with Aident

Claude model tokens and external Action credits are different meters. Aident Loadout can summarize the latter without reading your Claude Code transcripts.

Follow https://aident.ai/SETUP.md

Then run:

aident account auth status
aident audit summary --limit 100

Expected result: the first command confirms the active Aident account, and the second summarizes recent Loadout Action calls. Compare that report with the Actions you intended to run. It does not measure Claude tokens and should not be reconciled to a JSONL total as if they were the same unit.

Sources

Refresh this guide if Anthropic changes the JSONL schema, the local retention contract, /usage, or the authoritative billing source.

Home

Home

Home

Integrations

Integrations

Integrations

Vault

Vault

Vault

Audit

Audit

Audit

Arana Grande

Arana Grande

Arana Grande

Free

Free

Free

30-day audit summary

30-day audit summary

30-day audit summary

Daily action-call volume and the latest receipts from the Loadout audit trail.

Daily action-call volume and the latest receipts from the Loadout audit trail.

Daily action-call volume and the latest receipts from the Loadout audit trail.

View Audit

View Audit

View Audit

Loadout usage

Loadout usage

Loadout usage

617 action calls in the last 30 days

617 action calls in the last 30 days

617 action calls in the last 30 days

May 19 - Jun 17

May 19 - Jun 17

May 19 - Jun 17

10 active days

10 active days

10 active days

Less

Less

Less

More

More

More

Recent activity

Recent activity

Recent activity

Latest action-call receipts from connected agents

Latest action-call receipts from connected agents

Latest action-call receipts from connected agents

Apr 23, 09:23 AM

Apr 23, 09:23 AM

Apr 23, 09:23 AM

Shopify

Shopify

Shopify

Creates Or Updates An Asset For A Theme

Creates Or Updates An Asset For A Theme

Creates Or Updates An Asset For A Theme

Success

Success

Success

Apr 23, 09:21 AM

Apr 23, 09:21 AM

Apr 23, 09:21 AM

Shopify

Shopify

Shopify

Update Products Param Product Id

Update Products Param Product Id

Update Products Param Product Id

Success

Success

Success

Apr 23, 08:53 AM

Apr 23, 08:53 AM

Apr 23, 08:53 AM

Shopify

Shopify

Shopify

Update Products Param Product Id

Update Products Param Product Id

Update Products Param Product Id

Failed

Failed

Failed

Apr 22, 22:13 PM

Apr 22, 22:13 PM

Apr 22, 22:13 PM

Shopify

Shopify

Shopify

Create Product Image

Create Product Image

Create Product Image

Success

Success

Success

Apr 22, 22:12 PM

Apr 22, 22:12 PM

Apr 22, 22:12 PM

Shopify

Shopify

Shopify

Create Product Image

Create Product Image

Create Product Image

Success

Success

Success

Connected integration coverage

Connected integration coverage

Connected integration coverage

162

162

162

of 753 accessible connected

of 753 accessible connected

of 753 accessible connected

Callable actions

Callable actions

Callable actions

1,126

1,126

1,126

Vault credentials

Vault credentials

Vault credentials

8

8

8

Explore what's possible

Explore what's possible

Explore what's possible

See all Integrations

See all Integrations

See all Integrations

Google Ads

Google Ads

Google Ads

All available Goolge Ads tools via...

All available Goolge Ads tools via...

All available Goolge Ads tools via...

X (twitter)

X (twitter)

X (twitter)

All available X tools via...

All available X tools via...

All available X tools via...

Github

Github

Github

All available Github tools via...

All available Github tools via...

All available Github tools via...

Notion

Notion

Notion

All available Notion tools via...

All available Notion tools via...

All available Notion tools via...

Slack

Slack

Slack

All available Slack tools via...

All available Slack tools via...

All available Slack tools via...

Firecrawl

Firecrawl

Firecrawl

All available Firecrawl tools via...

All available Firecrawl tools via...

All available Firecrawl tools via...

753 integrations are available for loadouts.

753 integrations are available for loadouts.

753 integrations are available for loadouts.

Plug your entire stack into your AI agents.

Plug your entire stack into your AI agents.

Plug your entire stack into your AI agents.

Skip the integration headache. Plug 750+ tools into Claude Code, Codex, and OpenClaw in one go, and let your agents execute today.

Skip the integration headache. Plug 750+ tools into Claude Code, Codex, and OpenClaw in one go, and let your agents execute today.