dev.toJuly 12, 2026 AFFECTS EXAM
ModeloPrecio

I Measured Claude Code's Prompt-Cache Cost Three Ways. 85% of It Wasn't Mine to Trim.

I ran the same baseline Claude Code project through the VSCode extension, a VSCode-internal terminal, and a standalone terminal, then measur

---

title: I Measured Claude Code's Prompt-Cache Cost Three Ways. 85% of It Wasn't Mine to Trim.

published: true

tags: claudecode, anthropic, llm, vscode

description: I ran the same baseline Claude Code project through the VSCode extension, a VSCode-internal terminal, and a standalone terminal, then measur

---

I ran the same empty Claude Code project through three launch paths and read the cache tokens off the session log after every turn. One of those paths never touched the shared server-side cache at all — `cache_read` stayed at 0 on every run.

**TL;DR: the launch path (VSCode extension, VSCode-internal terminal, or a standalone terminal like iTerm2) decides whether Claude Code hits Anthropic's shared prompt cache. And even after trimming CLAUDE.md files, skills, and hooks, roughly 85% of the remaining `cache_creation` cost turned out to be Claude Code's own fixed overhead — not anything I control.**

What actually happened

Claude Code writes a JSONL log for every session under `~/.claude/projects/<project-key>/`, and each assistant turn in that log carries a `usage` object with `cache_creation_input_tokens` and `cache_read_input_tokens`. To see what was actually happening turn by turn instead of guessing from the monthly bill, I wrote a short script that reads the newest session log for the current project directory and prints those two numbers per turn.

python
#!/usr/bin/env python3
import json, os
from pathlib import Path

project_key = os.getcwd().replace("/", "-")
project_dir = Path.home() / ".claude/projects" / project_key
jsonl_files = sorted(project_dir.glob("*.jsonl"), key=lambda f: f.stat().st_mtime, reverse=True)

jsonl_path = jsonl_files[0]
turn = 0
for line in jsonl_path.read_text().splitlines():
    try:
        e = json.loads(line)
        usage = e.get("message", {}).get("usage", {})
        role = e.get("message", {}).get("role", "")
        if usage and role == "assistant":
            turn += 1
            print(f"turn {turn}: input={usage.get('input_tokens',0)} cache_create={usage.get('cache_creation_input_tokens',0)} cache_read={usage.get('cache_read_input_tokens',0)}")
            if turn >= 2:
                break
    except Exception:
        pass

I saved it as `measure-cache.py` and ran it from inside a baseline project — no CLAUDE.md, no hooks, no skills — right after opening a fresh session, then ran the exact same baseline through three different launch paths: the VSCode extension's chat panel, a terminal opened inside VSCode running the Claude Code CLI, and a standalone terminal (iTerm2) running the same CLI outside VSCode entirely.

The number that changed my mind

**Same project, three launch paths:**

| launch path | cache_creation | cache_read |

|---|---|---|

| VSCode extension (chat panel) | 39,054 | 10,270 |

| VSCode-internal terminal (CLI) | 39,054 | 10,270 |

| standalone terminal outside VSCode (e.g. iTerm2) | 50,985 | 0 |

`cache_read` costs about 1/10 of `cache_create` for the same toke

Read full article on dev.to