anthropics / anthropics/claude-code

[FEATURE] Add model, stop_reason, token usage and tool timing to hook payloads

Aperta
#91,767 3 commenti 0 reazioni 0 assegnatari Vedi su GitHub
area:hooks enhancement
Lingua principale
Python
Stelle
145k
Fork
23.1k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

### Preflight Checklist

- [x] I have searched [existing requests](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20label%3Aenhancement) and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)

### Problem Statement

I maintain an open-source desk device + plugin family ([Rubato_Plugins](https://github.com/lovaxi/Rubato_Plugins)) that mirrors agent state on physical hardware for several hosts (opencode, Cursor, OpenClaw, Codex). For Claude Code I use the official hooks — seven of them, from SessionStart to StopFailure.

The problem: **hook payloads carry almost no data** (session_id, transcript_path, cwd). To know the model, stop_reason, token usage, or tool names, my plugin must tail the session transcript JSONL in parallel — a second file-watcher per session, racing with Claude's own writes, parsing a format that is not documented as a stable contract.

Consequences:

- every hook consumer duplicates the same transcript-parsing layer (fragile, version-sensitive);
- extra latency between what Claude is doing and what external surfaces can display;
- streaming metrics (TTFT, tokens/sec) are simply unavailable at any latency — so honest duration estimation ("how long will this run take?") is impossible for external hardware and status surfaces, while the data itself exists inside the session.

### Proposed Solution

Keep the hooks exactly as they are — just make the payload self-sufficient, additively:

- on **all hooks**: include `model`
- on **Stop / StopFailure**: include `stop_reason`, `duration_ms`, and `token_usage { input, output, cache_read, cache_creation }`
- on **PostToolUse**: include `tool_duration_ms`
- (stretch) a turn-level metrics field with TTFT / output tokens-per-second — I understand streaming metrics may not be feasible; the usage fields alone are the high-value part.

Ideal UX: a hook consumer can mirror the full session — state, model, cost, honest durations — from hook events alone, without opening a single transcript file. All new fields are additive: existing consumers that ignore them are unaffected.

### Alternative Solutions

- Current workaround: tail `~/.claude/projects/.../*.jsonl` from a parallel daemon — works, but it parses an internal format, races with Claude's own writes, and still cannot see TTFT or streaming rate.
- The statusline input carries some session context, but it is a render surface, not an event stream an external device can subscribe to.
- An MCP server is the wrong layer for this: MCP servers serve the model; they do not observe the session.

### Priority

High - Significant impact on productivity

### Feature Category

Developer tools/SDK

### Use Case Example

1. I kick off a long refactor with Claude Code; my desk device shows Thinking → Generating so I stop alt-tabbing into the terminal.
2. On Stop, I want the device to show "took 4m 12s, 18k tokens" — so the user can honestly decide whether the next run justifies staying at the desk, and whether a break is due.
3. Today the Stop hook hands me a transcript path; a parallel daemon tails the JSONL, parses internal message shapes, and still cannot compute TTFT or per-request usage cleanly.
4. With structured hook payloads, the same integration shrinks to ~100 lines of version-stable code — and every status bar, dashboard, and device in the hooks ecosystem gets it for free.

### Additional Context

- The integration is shipped and verified end-to-end: [Rubato_Plugins](https://github.com/lovaxi/Rubato_Plugins) (seven hooks in use, including StopFailure and idle_prompt recovery).
- Cross-host parity: opencode events already carry per-call token usage, and OpenAI Codex exposes usage in its session data — Claude Code hooks are the gap.
- My device wire contract reserves `estSec` (estimated seconds); structured usage in hooks is the missing input for an honest estimate. Strictly additive proposal — no breaking changes.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Direzione di ricerca

Start by finding where Claude Code builds official hook payloads for SessionStart through StopFailure, especially Stop, StopFailure, and PostToolUse. Compare those payloads with the transcript JSONL data under ~/.claude/projects/.../*.jsonl to see where model, stop_reason, token_usage, duration_ms, and tool_duration_ms are already available. Done means the listed fields are added additively to hook events without requiring consumers to read the transcript.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
api, cli, developer-experience, tooling
Tipo di issue
Funzionalità
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Attiva
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.