← Zpět · 7. září 2026 · 8 min čtení

Napsal jsem 192 tokenů z deseti milionů

Pustil jsem audit spotřeby tokenů na svůj Claude Code. Cache read je 96 % a moje vstupy 0,002 %. Skript který to změření a co z rad kolem nesedí.

Když jsem tady v srpnu psal článek o pluginu pis-cesky, spotřebovala ta session 9 969 294 tokenů. Z toho jsem klávesnicí naťukal 192. Necelé dvě tisíciny procenta.

Ta čísla nejsou odhad. Leží v logu na disku a za chvíli ukážu, jak si je vytáhneš taky.

Podnět přišel z videa o spotřebě tokenů v Claude Code. Autor tam tvrdí, že za jeho limity nemůže to, co píše, ale to co se kolem toho všechno nabalí, jako důkaz přikládá audit prompt. Pustil jsem si ho na vlastní stroji, protože cizí čísla mi jsou k ničemu.

Proč to takhle roste

Model nemá paměť. Každý požadavek na API nese celou konverzaci od začátku, jinak by nevěděl, o čem se bavíš. Soubor přečtený ve čtvrtém kroku čtyřicetikrokové session tedy zaplatíš sedmatřicetkrát.

Že tě to nezruinuje, je jen tím, že se prefix konverzace cachuje. Čtení z cache stojí zhruba desetinu ceny běžného vstupu, zápis 1,25násobek při pětiminutové TTL a dvojnásobek při hodinové. Odtud plyne bod zvratu: u pětiminutové cache se ti to vrátí od druhého požadavku, u hodinové až od třetího.

V mém logu to vypadá takhle:

položka tokeny podíl
cache_read_input_tokens 9 575 016 96,05 %
cache_creation_input_tokens 325 606 3,27 %
output_tokens 68 480 0,69 %
input_tokens 192 0,0019 %

Kontext během té session narostl z 49 201 tokenů na 133 649. Nic velkého jsem nedělal, jen napsal jeden článek a průběžně ho opravoval.

Změř si to sám

Claude Code loguje každou session do ~/.claude/projects/<projekt>/*.jsonl, jeden JSON na řádek, a řádky s odpovědí modelu nesou objekt usage. Stačí ho sečíst přes všechny řádky:

import json, sys, os

for path in sys.argv[1:]:
    tot = {'cache_read_input_tokens': 0, 'cache_creation_input_tokens': 0,
           'input_tokens': 0, 'output_tokens': 0}
    ctx = []
    with open(path) as fh:
        for line in fh:
            try:
                rec = json.loads(line)
            except ValueError:
                continue
            usage = (rec.get('message') or {}).get('usage')
            if not isinstance(usage, dict):
                continue
            for key in tot:
                tot[key] += usage.get(key, 0) or 0
            ctx.append(sum(usage.get(k, 0) or 0 for k in
                           ('cache_read_input_tokens',
                            'cache_creation_input_tokens', 'input_tokens')))
    total = sum(tot.values())
    if not total:
        continue
    print(f"\n### {os.path.basename(path)} ({len(ctx)} turnů)")
    for key, value in sorted(tot.items(), key=lambda x: -x[1]):
        print(f"  {key:32} {value:>12,}  {100 * value / total:5.2f} %")
    print(f"  kontext: první turn {ctx[0]:,}, poslední {ctx[-1]:,}")

Spustíš to na konkrétní soubory:

python3 tokeny.py ~/.claude/projects/-Users-ty-projekt/*.jsonl

Vyjde ti vlastní číslo místo mého. Rozdíly mezi nastaveními jsou velké, takže tohle je jediná část článku, kterou opravdu doporučuju udělat, než budeš cokoli přenastavovat.

Můj vzorek má svoje meze. Obě session, které jsem proměřil (ta srpnová a jedna starší), byly psaní textu, ne čtení cizího kódu, a cache read u nich vyšel na 96,05 % a 94,61 %. Práce, při které agent čte stovky souborů, může vypadat jinak.

Co našel audit u mě

Prompt z popisu videa prochází sedm oblastí: paměťové soubory, MCP servery, model, hooky, subagenty, naplánované úlohy a cache. Celý ho dávám na konec článku.

Nejsilnější nález: globálně připojený MCP server godot-ai s padesátkou nástrojů a nahrával se mi i do Laravel projektu, který s Godot engine nemá co do činění. Vedle toho playwright a projektový laravel-boost.

Instrukční soubory dělají 21 KB: CLAUDE.md má 11 785 bajtů, AGENTS.md dalších 9 464. To se nahraje do každé session.

Naopak past s naplánovanými úlohami, kterou video označuje za nejhorší, se mě netýká vůbec. Můj crontab -l je prázdný. A žádný proxy ani gateway nastavený nemám, takže odložené načítání nástrojů běží tak, jak má.

Mám tři hooky, ale ani jeden neořezává výstup příkazů. Když si nechám pustit testy, spadne mi celý výpis do konverzace a veze se tam do konce session.

Co z rad platí

Přepínání modelu uprostřed session opravdu bolí a je to nejméně intuitivní věc na celém tématu. Cache je vázaná na model. Přepneš z Opusu na Sonnet, protože ti dochází limit, a celá dosavadní historie se přepočítá za plnou cenu místo desetinové. Chceš ušetřit ale zaplatíš víc. Totéž udělá změna úrovně effortu - ta cache zpráv zneplatní vždycky.

Compact je na tom podobně. Aby ti model napsal shrnutí konverzace, musí tu konverzaci ještě jednou celou přečíst. Kupuješ si tím kontinuitu, ne úsporu. /clear je zdarma, protože nic neposílá.

Co mi nesedí

Ve videu zazní, že vypínat a zapínat nástroje za běhu session nic nestojí, protože se prý jen připojují na konec. Anthropic to v dokumentaci k prompt cachingu píše jinak: definice nástrojů stojí na začátku promptu, a jejich přidání, odebrání nebo přeházení zneplatní celou cache. Kromě změny modelu je taková změna nástrojů jediné, co zahodí i cache nástrojů a systémového promptu, ne jenom historii zpráv.

Tak jsem si to změřil. Projel jsem všech pět session, co v tom projektu mám - tedy i ty dvě, ze kterých jsou procenta výš - dohromady 223 odpovědí modelu, a hledal turn, ve kterém cache_read_input_tokens propadne pod předchozí hodnotu. Nenašel jsem ani jeden. Prefix pokaždé rostl dál a cache_creation k němu jen přisypal, co přibylo.

Zkusil jsem rebuild i vynutit schválně. Načtení celého skillu do běžící session zapsalo 41 336 tokenů, a cache_read u téhož turnu zůstal na 97 178 - obsah se připsal na konec, prefix se nečetl znovu. Načtení schématu odloženého nástroje dopadlo stejně, cache_read pokračoval z 173 670 na 175 100.

Obojí tvrzení tedy platí. Dokumentace mluví o poli tools v požadavku na API, kde nástroje opravdu stojí na začátku. Claude Code s odloženým načítáním do toho pole podle všeho nesahá pokaždé, když se objeví nový nástroj, ale materializuje ho až na konec promptu, kam cache nedosáhne.

Jednu věc jsem neověřil: samotné připojení a odpojení MCP serveru přes /mcp. Na to bych musel sáhnout do konfigurace a session restartovat, čímž bych o měřený stav přišel. U tohohle kroku tedy pořád nevím.

Druhá věc, kterou bych nebral doslova: /usage prý pojmenuje konkrétní skill, nástroj nebo agenta, který ti sežral limit. Ve skutečnosti ukazuje jen spotřebu plánu. Rozpis podle nástrojů v něm nehledej.

Audit prompt

Tenhle text je z popisu videa, nechávám ho v originále tak, jak je:

Audit this setup for token waste. Do not fix anything. Report only.

Use your shell and file tools to measure each item. If you cannot invoke slash
commands yourself, ask me to run /context and /usage and paste the output, then
continue.

1. MEMORY
   Find every CLAUDE.md in scope: this project, parent directories, the user
   level one, and anything pulled in with @imports. Report each file's size in
   tokens. Flag any single file over 5k and any total over 10k.

2. TOOLS
   List connected MCP servers and how many tools each exposes. State plainly
   whether tool deferral is ACTIVE or NOT. Then check for a proxy or gateway
   (ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, any gateway variable) and say so
   loudly if you find one, because routing through a proxy silently turns
   deferral off and nothing warns you.

3. MODEL
   Report the current model and effort level and where each is set. Flag any
   mode that changes model automatically during a session, because every
   switch rebuilds the whole cache.

4. HOOKS
   List any PreToolUse hooks that rewrite noisy commands to produce less
   output. If there are none, say so, because unfiltered test and build output
   lands in context verbatim and is re-sent for the rest of the session.

5. SUBAGENTS
   List every agent file in the project and user agent directories. For each,
   report whether it sets an explicit model in frontmatter or inherits the
   main session's model.

6. SCHEDULED WORK
   List every cron, scheduled task and background job with its interval.
   Compare each interval against the prompt cache lifetime. Flag every one
   whose interval is longer, because those miss cache on every single fire.

7. CACHE
   Parse the newest session log under the projects directory. For every
   assistant turn, sum usage.cache_read_input_tokens,
   cache_creation_input_tokens, input_tokens and output_tokens. Report each as
   a percentage of the total. Also report the context size on the first turn
   and on the last turn.

Output one table, sorted by cost, highest first:

   FINDING | SEVERITY | EVIDENCE | WHAT IT IS COSTING ME

Severity is RED, AMBER or GREEN. Evidence is a number or a file path, never an
adjective.

Then one final line: the single highest-leverage change I should make. One
line, nothing else.

Rules: measure, do not estimate. Write UNKNOWN rather than guessing. Change no
file and no setting.

Bod 7 si klidně vyřeš skriptem výš, agent na to nepotřebuje číst půlmegový log do kontextu.

Já jdu opravit ten nález s Godotem. Snad vám ten článek a video pomůže tak jako pomohl mě👍.

Stačí psát část slova · ⌘K otevře hledání odkudkoliv

No results found