174 lines
8.9 KiB
Markdown
174 lines
8.9 KiB
Markdown
# Hooks ca functii + acces la context consumat — verificare documentatie oficiala
|
|
|
|
Data verificare: 2026-09-17. Metoda: WebFetch pe paginile oficiale (rezumate de un model
|
|
intermediar, nu HTML brut — unde continutul a fost trunchiat, marcat explicit mai jos) +
|
|
verificare empirica directa pe un `.jsonl` de pe disc.
|
|
|
|
## 1. Exista hook-uri definite ca FUNCTII (nu shell command)?
|
|
|
|
### In Claude Code (`settings.json` / plugin `hooks/hooks.json`) — NU
|
|
|
|
Pagina `https://code.claude.com/docs/en/hooks` defineste explicit tipurile de handler pentru
|
|
hook-uri:
|
|
|
|
> "Hooks are user-defined shell commands, HTTP endpoints, MCP tool calls, LLM prompts, or
|
|
> subagents that execute automatically at specific points in Claude Code's lifecycle."
|
|
|
|
Cinci tipuri de `type`, toate procese externe sau apeluri la distanta, niciunul „functie in-proces":
|
|
|
|
1. `"command"` — shell command (Bash/PowerShell)
|
|
2. `"http"` — POST catre un endpoint HTTP
|
|
3. `"mcp_tool"` — apel catre un tool MCP
|
|
4. `"prompt"` — evaluare printr-un prompt LLM single-turn
|
|
5. `"agent"` — subagent (experimental)
|
|
|
|
Confirmat separat pe `https://code.claude.com/docs/en/plugins-reference`, care listeaza acelasi
|
|
set de cinci tipuri pentru schema hook-urilor din plugin-uri si spune explicit:
|
|
|
|
> "There is no `function` type mentioned anywhere in the documentation."
|
|
|
|
Exemplu de schema (din `plugins-reference`):
|
|
|
|
```json
|
|
{
|
|
"hooks": {
|
|
"PostToolUse": [
|
|
{
|
|
"matcher": "Write|Edit",
|
|
"hooks": [
|
|
{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}\"/scripts/format-code.sh" }
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
**Concluzie punct 1a**: in Claude Code (inclusiv plugin-uri), hook-urile NU pot fi functii
|
|
JS/TS/Python in-proces — doar comenzi shell, HTTP, MCP tool, prompt LLM sau subagent.
|
|
|
|
### In Claude Agent SDK (TypeScript) — DA, dar cu rezerva NEDOCUMENTAT pe detalii
|
|
|
|
Pagina `https://code.claude.com/docs/en/agent-sdk/typescript` (redirect de la
|
|
`docs.claude.com/.../agent-sdk/typescript`) arata ca optiunea `hooks` a SDK-ului accepta
|
|
callback-uri, nu comenzi shell:
|
|
|
|
> `hooks` | `Partial<Record<`HookEvent`, `HookCallbackMatcher`[]>>` | `{}` | Hook callbacks for events
|
|
|
|
Asta e un mecanism DIFERIT de `settings.json` al Claude Code: aici hook-ul e literal o functie
|
|
TypeScript data la `query({ ..., hooks: {...} })`, ruland in acelasi proces Node ca aplicatia SDK.
|
|
|
|
**NEDOCUMENTAT - nu am putut extrage**: definitiile exacte de tip pentru `HookEvent`,
|
|
`HookCallback`, `HookCallbackMatcher`, `HookJSONOutput`, sau tipurile de input per eveniment
|
|
(`PreToolUseHookInput` etc.) — pagina e mare si WebFetch a trunchiat/rezumat continutul de doua
|
|
ori la rand, fara sa gaseasca sectiunea cu type body-urile (doar link-uri ancora `#hookevent`,
|
|
`#hookcallbackmatcher`, nerezolvate de rezumator). Nu pot afirma nici ca schema de input e identica
|
|
cu a hook-urilor `command`, nici ca difera — necesita citire directa a paginii (curl/browser),
|
|
nu WebFetch.
|
|
|
|
## 2. Primesc function hooks (SDK) un input mai bogat decat hook-urile `command`?
|
|
|
|
**NEDOCUMENTAT - nu am putut extrage.** Pagina SDK TS nu a livrat campurile exacte ale obiectului
|
|
de input trimis catre `HookCallback` (vezi punctul 1). Singurul camp relevant gasit pe acea pagina
|
|
a fost `maxThinkingTokens` (o optiune de configurare a sesiunii, nu un camp de input al hook-ului).
|
|
Nu exista nicio mentiune gasita de `usage`, `context_window` sau echivalent in continutul extras.
|
|
|
|
## 3. Ce primeste `statusLine` ca input, si acelasi obiect e disponibil vreunui hook?
|
|
|
|
Pagina `https://code.claude.com/docs/en/statusline` confirma ca `statusLine` e un mecanism separat
|
|
de hook-uri: un script shell propriu, care primeste JSON pe stdin cu date de sesiune, explicit
|
|
descris ca fiind pentru monitorizarea folosirii contextului:
|
|
|
|
> "The status line is a customizable bar at the bottom of Claude Code that runs any shell script
|
|
> you configure. It receives JSON session data on stdin and displays whatever your script prints,
|
|
> giving you a persistent, at-a-glance view of context usage, costs, git status..."
|
|
|
|
**NEDOCUMENTAT - nu am putut extrage** schema JSON exacta trimisa pe stdin (campurile
|
|
`context_window.used_percentage` etc.) — fetch-ul a livrat doar introducerea paginii, nu tabelul
|
|
de schema (posibil mai jos in pagina, trunchiat de rezumator).
|
|
|
|
Nu am gasit, in niciuna din paginile de hook-uri (`hooks`, `hooks-guide`, `plugins-reference`),
|
|
vreo mentiune ca acelasi obiect JSON dat lui `statusLine` ar fi disponibil si unui hook obisnuit.
|
|
Structural, `statusLine` e configurat separat de `hooks` in `settings.json` si documentat ca
|
|
mecanism de sine statator, nu ca un tip de hook din lista de 5 (`command`/`http`/`mcp_tool`/
|
|
`prompt`/`agent`).
|
|
|
|
## 4. Exista un eveniment de hook dedicat contextului (prag, PreCompact cu date de ocupare)?
|
|
|
|
Pagina `hooks` listeaza evenimentul `PreCompact` ("Before context compaction") si `PostCompact`,
|
|
dar continutul extras nu contine schema de input pentru `PreCompact`:
|
|
|
|
> `PreCompact` are matcher pe ce a declansat compactarea (`"manual"` sau `"auto"`), dar campurile
|
|
> JSON de input nu sunt specificate in continutul extras.
|
|
|
|
Nu exista, in continutul extras din niciuna dintre pagini, un eveniment de tip "context threshold"
|
|
separat de `PreCompact`/`PostCompact`. **NEDOCUMENTAT - nu am putut extrage** schema completa a
|
|
`PreCompact` (posibil contine deja procente de ocupare — nu s-a putut confirma nici infirma).
|
|
|
|
Campurile COMUNE confirmate pentru toate evenimentele de hook (din tabelul extras pe pagina
|
|
`hooks`):
|
|
|
|
```
|
|
session_id, prompt_id, transcript_path, cwd, scratchpad_dir, permission_mode,
|
|
effort.level, hook_event_name, agent_id (doar subagenti), agent_type (doar subagenti)
|
|
```
|
|
|
|
Niciun camp de tokeni/usage/context in aceasta lista. Coincide cu dovada empirica deja detinuta
|
|
(inputul real al `SubagentStop` capturat anterior nu are camp de tokeni).
|
|
|
|
## 5. Schema unei linii `assistant` din transcriptul `.jsonl` — are `usage`?
|
|
|
|
**Verificat direct pe disc, DA** — nu doar documentatie, dovada empirica reala:
|
|
|
|
```
|
|
grep -o '"usage":{[^}]*}' bdb0bf8c-a086-4d46-b08d-545a92e5c32c.jsonl | head -3
|
|
```
|
|
|
|
rezultat (identic pe primele linii verificate):
|
|
|
|
```json
|
|
"usage":{"input_tokens":2,"cache_creation_input_tokens":34191,"cache_read_input_tokens":31003,"output_tokens":1710,"output_tokens_details":{"thinking_tokens":198}
|
|
```
|
|
|
|
Deci fiecare linie `assistant` din `.jsonl` are un obiect `message.usage` cu:
|
|
`input_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens`, `output_tokens`,
|
|
`output_tokens_details.thinking_tokens`.
|
|
|
|
Asta e citibil de orice proces cu acces la fisier (inclusiv un hook `command`, daca i s-ar da
|
|
calea) — dar hook-ul primeste doar `transcript_path` ca referinta, nu campul de usage direct in
|
|
inputul lui JSON. Un hook `command` ar putea *citi singur* fisierul si insuma `usage` peste toate
|
|
liniile `assistant` ca sa aproximeze contextul consumat — asta nu necesita „function hooks",
|
|
functioneaza si cu un hook shell obisnuit care are `jq`/`python` la indemana si stie
|
|
`transcript_path`.
|
|
|
|
## Verdict
|
|
|
|
**Poate un hook sa afle contextul consumat, si pe ce cale — da, dar nu prin niciun camp direct din
|
|
inputul JSON al hook-ului**, indiferent daca hook-ul e `command` sau (in SDK, nu in Claude Code)
|
|
o functie in-proces:
|
|
|
|
- **Calea documentata si confirmata empiric**: orice hook `command` (sau function-hook din SDK,
|
|
daca primeste `transcript_path` in input — nedocumentat exact, dar plauzibil, campul e comun
|
|
tuturor evenimentelor conform tabelului din `hooks`) poate **citi singur** `transcript_path` de
|
|
pe disc si insuma `message.usage` din liniile `assistant` ca sa aproximeze tokenii consumati.
|
|
Asta confirma ce a spus deja Marius implicit: se poate afla, dar prin citire activa a
|
|
transcriptului, nu pentru ca hook-ul primeste un camp gata calculat.
|
|
- **Nu exista, in ce am putut extrage din documentatie, niciun camp `usage`/`context_window`/
|
|
`tokens` in inputul JSON dat direct hook-ului** (nici la `command`, nici — din cate am putut
|
|
verifica — mentionat pentru function hooks din SDK).
|
|
- **`statusLine` e mecanismul care primeste `context_window.used_percentage` gata calculat**, dar
|
|
e un canal separat de `hooks` in `settings.json`, nu un tip de hook; nu am gasit dovada ca acel
|
|
obiect ar fi expus si catre hook-uri.
|
|
- Afirmatia initiala („niciun hook Claude Code nu poate afla cat context s-a consumat") e
|
|
**partial gresita**: un hook nu primeste tokenii de-a gata, dar poate sa-i afle citind singur
|
|
`transcript_path` — cale disponibila oricarui hook `command`, nu doar unor ipotetice „function
|
|
hooks".
|
|
|
|
## Goluri ramase (NEDOCUMENTAT, de reverificat cu citire directa a paginii, nu WebFetch)
|
|
|
|
- Schema completa de tip TypeScript pentru `HookCallback`/`HookCallbackMatcher`/`HookEvent` din
|
|
SDK (`code.claude.com/docs/en/agent-sdk/typescript`) — pagina prea mare, WebFetch a trunchiat de
|
|
doua ori la rand.
|
|
- Schema JSON completa trimisa pe stdin catre `statusLine` (`code.claude.com/docs/en/statusline`).
|
|
- Schema completa de input pentru `PreCompact` (`code.claude.com/docs/en/hooks`).
|