[FEATURE] Expose token usage and cost data in hook inputs

Open 💬 23 comments Opened Nov 4, 2025 by cassiodias

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Currently, hooks receive session metadata (session_id, transcript_path, cwd, permission_mode) but NO token usage or cost information. This limitation prevents:

  1. Real-time budget monitoring: Cannot trigger warnings when approaching token limits
  2. Context-aware decisions: Cannot adapt behavior based on current token consumption
  3. Automated session management: Cannot implement intelligent save/compact strategies based on cost
  4. Integration with external systems: Cannot automatically log usage metrics to monitoring tools

Users must manually run /cost or /usage commands, or parse transcript JSONL files post-session, neither of which supports real-time automation.

Use Case: my tool for context monitoring
I'm building a tool (semantic memory system for engineering context) that needs to monitor Claude Code's 200k token window. A PostToolUse hook could automatically:

#!/bin/bash
# PostToolUse hook for my tool context monitoring

input=$(cat)
current_tokens=$(echo "$input" | jq -r '.usage.total_tokens')
session_cost=$(echo "$input" | jq -r '.usage.total_cost_usd')

# Alert if approaching context limit (80% threshold)
if [ "$current_tokens" -gt 160000 ]; then
  echo '{"type": "warning", "message": "Context usage at 80% ('"$current_tokens"'/200k tokens). Consider /compact or saving."}'
fi

 Log to external monitoring system
curl -s -X POST http://localhost:8081/context/monitor \
  -H 'Content-Type: application/json' \
  -d "{\"current_tokens\": $current_tokens, \"cost\": $session_cost}"

Currently impossible because hooks don't receive token/cost data.

Related Issues

  • #8861: Requests token data in status line API (different feature)
  • #9293: Pre-Exit hook for cost display (closed as duplicate)
  • #10593: Real-time token usage indicator
  • #8832: Customizable status bar with token widgets

None of these specifically address exposing token data TO hooks as input.

Proposed Solution

Add token usage and cost fields to the JSON input passed to hooks via stdin:

{
  "session_id": "abc123",
  "transcript_path": "/path/to/transcript.jsonl",
  "cwd": "/project/path",
  "permission_mode": "ask",
  "hook_event_name": "PostToolUse",
  "usage": {
    "total_tokens": 45230,
    "input_tokens": 38000,
    "output_tokens": 7230,
    "cache_read_tokens": 12000,
    "cache_creation_tokens": 5000,
    "total_cost_usd": 0.87,
    "percentage_of_context_window": 22.6
  },
  "limits": {
    "context_window_tokens": 200000,
    "session_remaining_tokens": 1250000,
    "weekly_remaining_tokens": 8500000
  }
}

Implementation Notes

  • Token data is already tracked internally (visible via /cost and /usage)
  • Status line API already receives token data (per #8861 discussion)
  • Extending hook inputs to include this data should be straightforward
  • All hook types would benefit, but PostToolUse and PreCompact are highest priority

Benefits

  1. Proactive context management: Hooks can trigger compaction before hitting limits
  2. Budget enforcement: Organizations can implement hard spending caps
  3. Usage analytics: Stream metrics to external monitoring/observability platforms
  4. Intelligent session management: Auto-save expensive sessions to memory systems
  5. User experience: Automated warnings prevent surprise context window errors

Alternative Workarounds (Why They're Insufficient)

  1. Parse transcript JSONL: Requires file I/O, complex parsing, only works post-session
  2. Status line API: Display-only, not accessible to hooks
  3. Manual /cost command: Requires user intervention, not automatable in hooks

Community Interest

Multiple issues (#8861, #10593, #7111) demonstrate strong demand for better token visibility. Exposing this data to hooks would enable the community to build powerful automation on top of Claude Code.

Alternative Solutions

_No response_

Priority

Medium - Would be very helpful

Feature Category

CLI commands and flags

Use Case Example

_No response_

Additional Context

_No response_

View original on GitHub ↗

23 Comments

MarvDann76 · 7 months ago

I think this would be a great addition to the status line. Context and Cost awareness is key as we are working. /context and /usage is great but I think more a persistent reminder would be even more valuable as an option to switch on / off easily. I did try implementing this myself but it wasn't giving me accurate real-time info.

github-actions[bot] · 6 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

cassiodias · 6 months ago

Hey, do you have any response? This is interesting to the community.

cassiodias · 5 months ago

?

jbogacz · 5 months ago

Strong support for this. Hooks are currently blind to session costs!

cassiodias · 5 months ago

This directly addresses a real usability problem: instruction rot during context compaction. When Claude Code compacts the conversation, user-defined rules (like "no emojis in code") get diluted or lost entirely. After 2-3 compactions, Claude starts ignoring instructions that were clear at the start of the session.

Exposing token usage to hooks (especially a PreCompact hook) would let users:

  • Reinject critical instructions before compaction
  • Monitor context usage proactively
  • Build automation to preserve session integrity

The data already exists internally (/cost, /usage commands work) - this is about exposing it where it's useful.

Even a brief acknowledgment of whether this is on the roadmap would be appreciated. Radio silence on community issues isn't a great look :(

junaidtitan · 4 months ago

For anyone who needs this today — cozempic already extracts token usage from the usage blocks in session JSONL assistant messages, with a heuristic fallback for messages that lack them. cozempic diagnose shows per-session token counts and context percentage bars. Not as clean as native hook support would be, but it works now.

cassiodias · 4 months ago
For anyone who needs this today — cozempic already extracts token usage from the usage blocks in session JSONL assistant messages, with a heuristic fallback for messages that lack them. cozempic diagnose shows per-session token counts and context percentage bars. Not as clean as native hook support would be, but it works now.

Great @junaidtitan - will check that for sure

cassiodias · 4 months ago

So, I have read the Claude Mem and Cozempic and did a simpler hook-based approach and ran a simple POC; it works!

If anyone is interested in how to get hooks properly and inject info after compacting, please take a look at https://github.com/cassiodias/rekall-hook.

0xadri · 4 months ago

Strong support for this. Hooks are currently blind to session costs!

ordinarybob · 4 months ago

Yes, I need this.

Use case: Long-running multi-hour sessions (50-100+ turns) where the AI accumulates critical state — decisions, discoveries, work status. Auto-compaction destroys the AI's ability to reconstruct this accurately.

What I need: At a configurable context threshold (e.g., 75%), auto-inject a user message that triggers the AI to synthesize and persist session state to a checkpoint file (as per my criteria/instructions in an MD file) — before compaction makes that impossible.

Proposed shape:

{
"contextTriggers": [
{ "threshold": 75, "message": "save to the scratchpad.", "once": true }
]
}

The extension already tracks used_percentage and can send messages. This just connects them with a conditional. PreCompact hooks don't solve this because they only run shell commands — they can't prompt the AI to synthesize state, and there's no action window before compaction proceeds.

andresvanegas19 · 4 months ago

We would like to have this to enhance our evals and see which agent prompt is optimized for a given task https://github.com/anthropics/claude-code/issues/32842

milobird · 4 months ago

I would find this really useful for the Stop hook in particular.

TylerMcCraw · 3 months ago

We'd like to use a context threshold hook to automatically trigger a CLAUDE.md revision skill that persists session learnings before compaction. Currently PreCompact fires too late — there's not enough token budget left to run a multi-step skill that reads files, analyzes the session, and writes updates.

smigolsmigol · 3 months ago

Until hooks get cost data natively, there are two workarounds that work today:

MCP tools (query-based): an MCP server with tools for session cost, project costs, agent attribution, cache savings, and cost forecast. Works with Claude Code, Cline, and Cursor. Auto-detects which tools are installed.

SessionEnd hook (event-driven): the same package can run as a hook that parses the transcript on session end and prints cost summary automatically. No manual queries needed.

{
  "hooks": {
    "SessionEnd": [{"hooks": [{"type": "command",
      "command": "npx @f3d1/llmkit-mcp-server --hook"}]}]
  }
}

Both read local data, no API key or account needed.

npm: @f3d1/llmkit-mcp-server
github: https://github.com/smigolsmigol/llmkit

digitalpromptmarket-beep · 3 months ago

GitHub Comment Draft — anthropics/claude-code #11008

Issue: [FEATURE] Expose token usage and cost data in hook inputs
Status: OPEN, NOT LOCKED (15 comments)
Action: NEEDS AUDITOR REVIEW before posting.

---

Prepared Comment

This is exactly the right feature request. The gap between "the data exists in JSONL files" and "hooks can act on it in real-time" is where a lot of value is stuck.

Until this ships natively, I've been working around it by building post-session analysis tooling that parses the same JSONL transcripts. It's not real-time (which is what this issue really needs), but it does answer the "where did my budget go?" question after the fact.

The data in those JSONL files is surprisingly rich -- per-turn breakdowns of input, output, cache_read, and cache_creation tokens, model identifiers, tool call metadata, and sub-agent spawn events. Enough to reconstruct a full cost attribution report.

What the analysis reveals that /cost doesn't:

  • Which individual turns consumed the most tokens
  • Cache efficiency (creation vs. read ratio -- are you paying to create cache that never gets reused?)
  • Model misallocation (Opus on simple tasks that Sonnet handles equally well)
  • Sub-agent overhead (each sub-agent duplicates context)

If anyone building hooks wants to consume this data programmatically:

npx agent-forensics analyze ~/.claude/projects/-Users-you/ --json

The --json flag outputs structured data that a hook or monitoring system could ingest. Not a substitute for native hook support (that's the real solution), but useful for post-session automation today.

Preview the output format: curl -s https://api.agentsconsultants.com/forensics/sample | jq .

Full disclosure: I built this tool. It's MIT-licensed and runs entirely locally.

digitalpromptmarket-beep · 3 months ago

GitHub Comment Draft — anthropics/claude-code #11008

Issue: [FEATURE] Expose token usage and cost data in hook inputs
Status: OPEN, NOT LOCKED (15 comments)
Action: NEEDS AUDITOR REVIEW before posting.

---

Prepared Comment

This is exactly the right feature request. The gap between "the data exists in JSONL files" and "hooks can act on it in real-time" is where a lot of value is stuck.

Until this ships natively, I've been working around it by building post-session analysis tooling that parses the same JSONL transcripts. It's not real-time (which is what this issue really needs), but it does answer the "where did my budget go?" question after the fact.

The data in those JSONL files is surprisingly rich -- per-turn breakdowns of input, output, cache_read, and cache_creation tokens, model identifiers, tool call metadata, and sub-agent spawn events. Enough to reconstruct a full cost attribution report.

What the analysis reveals that /cost doesn't:

  • Which individual turns consumed the most tokens
  • Cache efficiency (creation vs. read ratio -- are you paying to create cache that never gets reused?)
  • Model misallocation (Opus on simple tasks that Sonnet handles equally well)
  • Sub-agent overhead (each sub-agent duplicates context)

If anyone building hooks wants to consume this data programmatically:

npx agent-forensics analyze ~/.claude/projects/-Users-you/ --json

The --json flag outputs structured data that a hook or monitoring system could ingest. Not a substitute for native hook support (that's the real solution), but useful for post-session automation today.

Preview the output format: curl -s https://api.agentsconsultants.com/forensics/sample | jq .

Full disclosure: I built this tool. It's MIT-licensed and runs entirely locally.

yurukusa · 3 months ago

/tmp/issue-11008-comment.md

kzmx23 · 2 months ago

This is very useful feature. Vote +1.
During agent team operation an orchestrator agent can be natively notified about team mate architect agent 80% context window. It can gracefully stop any agent operation even if an agent will be busy by long running task and won't receive team-lead message via standard protocol. It can be done by using tmux send-keys -t [target-pane] "[command]" [key] feature. So the agent then can take a planned handoff and precompact actions.

komisla · 2 months ago

Working real-time workaround + key technical finding

After debugging this in depth in a Windows/PowerShell environment, I found two concrete points that may help prioritize the fix.

1. The field already exists — it is just missing from in-session events

context_window_percentage does appear in the Stop hook payload, but only when the session is fully closed.

During an active session, Stop fires correctly after every assistant response, but the field is absent:

// In-session Stop, every response — field missing:
{
  "session_id": "...",
  "transcript_path": "...",
  "hook_event_name": "Stop",
  "stop_hook_active": false,
  "last_assistant_message": "..."
}
// Session-close Stop — field present:
{
  "hook_event_name": "Stop",
  "context_window_percentage": 47.2,
  ...
}

The data is clearly computed internally. It just is not being passed through to in-session Stop events.

Minimal fix: populate context_window_percentage and context_window_size in every Stop event, not just the final one.

2. Transcript JSONL workaround works in real time, not just post-session

The issue description lists transcript parsing as “only post-session”, but that is not quite right.

Since Stop fires after every response and the transcript is updated at that point, it is possible to read the last assistant entry’s usage data for a real-time approximation:

#!/bin/bash
input=$(cat)

# Use native field if present (session close only, currently)
pct=$(echo "$input" | jq -r '.context_window_percentage // empty')

# Fallback: parse transcript
if [ -z "$pct" ]; then
  transcript=$(echo "$input" | jq -r '.transcript_path // empty')

  if [ -n "$transcript" ] && [ -f "$transcript" ]; then
    pct=$(python3 - "$transcript" <<'EOF'
import sys
import json

with open(sys.argv[1], "rb") as f:
    f.seek(max(0, -12000), 2)
    chunk = f.read().decode("utf-8", errors="ignore")

for line in reversed(chunk.splitlines()):
    try:
        e = json.loads(line)

        if e.get("type") == "assistant":
            u = e.get("message", {}).get("usage", {})

            if u:
                total = (
                    u.get("input_tokens", 0)
                    + u.get("cache_read_input_tokens", 0)
                    + u.get("cache_creation_input_tokens", 0)
                )
                print(round(total / 200000 * 100, 1))
                break

    except Exception:
        pass
EOF
    )
  fi
fi

[ -n "$pct" ] && echo "{\"pct\":$pct}" > ~/.claude/ctx.json

This gives a per-response update during active sessions.

The calculated value includes all cached input, including system prompt, autocompact buffer, and related context. Therefore, it reads slightly higher than /context shows, but it is likely a more accurate picture of what is actually being sent to the model.

Environment

  • Claude Code VS Code extension
  • Windows 11
  • claude-sonnet-4-6
  • Reproduced across multiple Claude Code versions
norika1207-lab · 1 month ago

One narrower contract that would make hooks useful without turning them into a full analytics API: emit a small, stable session_pressure object on Stop, PostToolUse, and PreCompact.

For example:

{
  "session_pressure": {
    "context_window_used_percentage": 72.4,
    "context_window_size": 200000,
    "last_turn_input_tokens": 18420,
    "last_turn_output_tokens": 910,
    "cache_read_input_tokens": 140000,
    "cache_creation_input_tokens": 6200,
    "compaction_count": 1,
    "measurement_source": "runtime"
  }
}

The important part is not exact billing. It is operational control: before launching another tool call, subagent, or long write, a hook should know whether the session is approaching the point where memory quality and handoff reliability degrade.

This is becoming more important as coding agents move from local interactive use toward remote/mobile starts and longer autonomous runs. In that mode, the user is not staring at /context or /usage; the automation needs enough telemetry to decide “continue, checkpoint, compact, or stop and ask.”

Psykepro · 1 month ago

Thanks for all the work on hooks.

While reviewing this issue, it appears the runtime already computes and exposes at least part of the requested information.

As noted by @komisla, context_window_percentage is present in the final Stop hook payload when a session closes:

{   
  "hook_event_name": "Stop",
  "context_window_percentage": 47.2
}

This suggests the underlying telemetry already exists and is available to the hook system.

Would it be possible to expose the same data consistently during active sessions?

Even a minimal payload such as:

{
  "session_pressure": {
    "context_window_used_percentage": 72.4,
    "context_window_size": 200000
  }
}

on Stop, PostToolUse, and ideally PreCompact would unlock many use cases:

  • automatic memory checkpointing
  • proactive compaction
  • external memory systems
  • long-running autonomous agents
  • orchestrator/sub-agent handoffs
  • budget and context monitoring

At this point the request is less about adding a new capability and more about making already-computed runtime telemetry available before compaction or session termination occurs.

Is there an existing issue tracking the rollout of context_window_percentage to active-session hooks, or is this still considered not planned?

Necmttn · 24 days ago

A small session_pressure object would cover most hook use cases without turning hooks into a billing API.

Fields: context window used %, window size, last turn input/output tokens, cache read/create tokens, compaction count, session id, sampled_at, and measurement_source. Emitting that on Stop, PostToolUse, and PreCompact would let hooks checkpoint, warn, or switch to handoff mode before the session is already too full to recover.

Generated with ax - https://github.com/Necmttn/ax