Why Your Coding Agents Burn Tokens in the Dark A developer built Thermal, a local monitoring tool, after discovering that autonomous coding agents such as Devin and OpenCode consume tokens in ways that make per-dollar cost attribution impossible. The developer's example shows a single agent session burning roughly 215,000 tokens for a two-line test fix, driven by context accumulation, repeated state inspection, subagent spawning and hidden reasoning tokens in models like o3-mini and DeepSeek-R1. The developer rejected piping private codebases and session transcripts into cloud-hosted SaaS monitoring platforms, citing developer privacy and craftsmanship concerns. A few months ago, around two in the morning, I was sitting in front of my terminal watching three separate tmux panes hum with activity. In one window, Devin was refactoring an AST parser. In another, OpenCode was executing a test-driven loop against a flaky API endpoint. In a third, an experimental agent was indexing symbol references across a dozen repositories. From the outside, it looked like the ultimate dream of modern software development. The screen was a cascading waterfall of syntax highlights, bash commands, unified diff blocks, and passing test assertions. The manual friction of writing boilerplate had vanished into thin air. Then the monthly API invoices arrived. The numbers were not ruinous, but they were deeply unsettling. Not because of the absolute dollar figure, but because I had no honest way of answering the most fundamental engineering question: what did each of those dollars actually purchase? When you work alongside human engineers, you have an intuitive grasp of where time and energy go. You know whether an architectural refactor took three hours or three days. But with autonomous coding agents, token consumption happens entirely in the dark. As I learned firsthand when evaluating coding agents on real tasks https://jadmadi.net/posts/power-of-jules/ , fluency is not the same as discipline. An agent gets trapped in an internal linting dispute, consumes six hundred thousand tokens quietly re-reading the entire project schema on every single turn, and reports back with a single-line patch. You pay for forty-seven model invocations, and you have no idea which prompt triggered the avalanche. We had traded developer ergonomics for financial blindness. And the prescribed solutions piping private codebases and session transcripts into yet another closed, cloud-hosted SaaS monitoring platform felt like an insult to developer privacy and software craftsmanship. So I decided to build Thermal https://jadmadi.net/project/thermal/ . The Compounding Geometry of Agent Spend Most developers still calculate AI costs using a simple calculator mental model: you send a prompt of five hundred tokens, get back a thousand tokens, and pay pennies. That model dies the moment you deploy autonomous agents. In an agentic loop, token expenditure does not scale linearly with output code. It scales exponentially with execution uncertainty . As I explored when breaking down Princeton’s research on how agent skills stabilize execution https://jadmadi.net/posts/demystifying-agent-skills/ , an agent does not merely answer questions; it observes, reflects, probes tool outputs, and adjusts its internal plan. flowchart TD subgraph StepLoop "Compounding Token Footprint" A "User Task: 'Fix flaky test'" -- B "Step 1: Read Workspace Tree 45k tokens " B -- C "Step 2: Run Test Runner 12k tokens output " C -- D "Step 3: Reread File + Test Traces 65k tokens " D -- E "Step 4: Attempt Speculative Edit 15k tokens " E -- F "Step 5: Rerun Tests & Self-Correct 78k tokens " end F -- G "Total Billed: ~215,000 Tokens for a 2-Line Fix" Consider what happens inside a single agent session: 1. Context Accumulation: On step one, the system prompt, tool schemas, and repository summary consume thirty thousand tokens. 2. Execution Traces: By step five, the agent has executed three failing shell commands. The terminal stdout and stderr now live inside the message history. 3. Repeated State Inspection: To decide what to do on step six, the model must re-read the entire accumulated dialogue from scratch. 4. Subagent Spawning: When the primary agent spawns a subagent, a fresh context window opens, often inheriting another slice of the codebase. 5. Hidden Reasoning Tokens: Frontier reasoning models such as o3-mini or DeepSeek-R1 generate thousands of hidden thinking tokens per turn to deliberate before emitting a single line of actionable code. A two-line patch in a test runner can easily burn three hundred thousand tokens across eight round-trips. If that agent runs on a frontier model, an afternoon of aggressive tinkering can quietly cost twenty or thirty dollars. Multiply that across five tmux windows, seven days a week, and three different agent CLIs, and you are no longer doing software development. You are running an unmonitored compute furnace. Why SaaS Dashboards Miss the Point The standard Silicon Valley answer to this problem is predictable: sign up for a monitoring service, install their npm package, configure an HTTP reverse proxy HTTP PROXY , and stream every prompt, file path, and agent transcript to their cloud. I refuse to do that. My local code is my own. The architecture decisions, private client keys, internal database schemas, and scratch notes that pass through my agent sessions have no business living on a third-party server. Furthermore, when you work far from central US data centers, adding an external telemetry proxy injects a punishing latency tax into every single turn, a reality I wrote about in Latency Is Political When You Live Far from the Center https://jadmadi.net/posts/latency-is-political-when-you-live-far-from-the-center/ . It violates the offline-first resilience of Unix tools, breaks when tools enforce custom certificate verification, and creates yet another recurring subscription. When I started digging into how agent harnesses work on disk, I noticed something fascinating: the telemetry was already there. Every modern coding agent leaves a rich local trail on your filesystem: - Claude Code streams JSONL event logs under ~/.claude/projects/ . - Codex maintains state 5.sqlite alongside rollout JSONL logs. - OpenCode / MiMoCode records session graphs in ~/.opencode/ SQLite databases. - Grok logs completed turns in updates.jsonl . - Devin, Gemini CLI / Antigravity, Nous Hermes, and DeepSeek all maintain local SQLite databases or structured JSON files. The agents were not hiding their costs. They were diligently saving them to disk. We were simply ignoring the files. We did not need another cloud service. We needed a fast, local-first lens. Building Thermal: Architecture of a Zero-Telemetry FinOps Engine When I sat down to design Thermal, I set three non-negotiable principles for myself: 1. Zero Cloud Telemetry & Zero Daemons: Thermal is 100% offline. It never makes an outbound phone-home ping, requires no cloud accounts, and installs no persistent background processes eating battery and RAM. 2. Sub-10ms Cached Invocations: In order to fit naturally into interactive developer workflows even rendering inside a shell prompt like Starship or .zshrc , invoking thermal must return in single-digit milliseconds. 3. Strictly Non-Invasive & Read-Only: Thermal never injects wrappers or modifies user databases. It reads what exists without interfering with active tools. To achieve this, I wrote Thermal in Go as a zero-CGO, statically linked binary. flowchart LR subgraph Harnesses "14 Local Agent Harnesses" H1 "Claude Code ~/.claude " H2 "OpenCode / MiMoCode" H3 "Codex state 5.sqlite " H4 "Devin, Grok, Agy, Hermes..." end subgraph ThermalCore "Thermal Go Core" D "Parallel Harness Scanner" -- M "Read-Only SQLite mmap & JSONL Engine" M -- C "Delta Cache ~/.cache/thermal/ " C -- P "Disjoint Token Normalization & Pricing" P -- S "Unified FinOps Aggregator" end subgraph Presentation "Terminal Output" S -- TUI "Interactive Bubble Tea TUI" S -- CLI "Terminal Heatmap & Scriptable JSON" end Harnesses -- D 1. Pure-Go SQLite and Memory-Mapped Zero-Copy I/O Many agent harnesses run on SQLite. If an agent is actively coding while Thermal executes, opening the database with a standard read-write connection causes immediate lock contention database is locked . Thermal opens all SQLite databases in pure read-only URI mode and immediately activates memory mapping via PRAGMA mmap size : // Pure-Go SQLite modernc.org/sqlite : CGO-free, read-only, zero lock contention db, err := sql.Open "sqlite", "file:"+dbPath+"?mode=ro" if err = nil { return err } defer db.Close // Memory-map 256MB of page cache for instant scanning without heap allocation if , err := db.Exec "PRAGMA mmap size=268435456" ; err = nil { return err } Because Thermal uses modernc.org/sqlite https://pkg.go.dev/modernc.org/sqlite compiled with CGO ENABLED=0 , the binary remains fully statically linked. It compiles across Linux, macOS, and Windows without requiring GCC toolchains or dynamic C libraries. 2. The Sub-10ms Delta Snapshot Cache Scanning gigabytes of raw transcripts on every shell invocation is an anti-pattern. To guarantee sub-10ms response times, Thermal employs an incremental disk-backed delta snapshot cache in ~/.cache/thermal/