Reading Claude's Output
A good prompt is half the job; the other half is reading what comes back without being fooled by fluency. This chapter opens up a real, short session and shows every event in it: each tool Claude called, what came back, and what you were finally shown. Then it shows what the cost and permission fields mean, and how to ask Claude to explain what it did, and how to check that explanation against the log.
One Answer, Several Turns
Claude Code answers by looping: the model asks to use a tool, Claude Code runs it (if permitted) and hands the result back, and the model decides whether to call another tool or write the answer (Source 1). Each trip around that loop is a turn. A question that looks like one answer to you may be several turns underneath.
Two consequences. First, more turns cost more, because the conversation so far is sent again each turn (the cached part is cheaper). Second, you can only trust the tool calls, not the prose: the log below shows what actually ran.
A Complete Timeline
The prompt, sent with claude -p and --output-format stream-json --verbose, which emits one JSON event per step:
| # | Event | Content |
|---|---|---|
| 1 | Grep call | {"pattern": "search|title", "glob": "**/*[Tt]est*", "-i": true, "output_mode": "content"} |
| 2 | Result returned to Claude | 1353 characters; starts: src/test/java/com/example/bookshelf/BookControllerTest.java:32: .andExpect(jsonPath("$[0].title").value("Clean Code")); src/test/java/com/example |
| 3 | Claude thinks | (reasoning is not recorded in the log) |
| 4 | Read call | {"file_path": "<project>/src/test/java/com/example/bookshelf/BookSearchTest.java"} |
| 5 | Result returned to Claude | 1175 characters; starts: 1 package com.example.bookshelf; 2 3 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 4 import static org.springframework |
| 6 | Answer shown to you | Only one test covers title search: - `titleSearchIsCaseInsensitiveAndSorted`, in `src/test/java/com/example/bookshelf/BookSearchTest.java:21`. - It calls `GET /api/books/search?title=CLEAN`. - It expects a 200 response with 2 results, "Clean Architecture" first and "Clean Code" second. - So it checks case-insensitive matching and sorted order. I searched the test files for "search" and "title", and `BookSearchTest` is the only file that exercises the search endpoint. `BookControllerTest` and `BookApiIntegrationTest` only mention `title` as a field on books they create or list. Nothing tests a search with no matches, a missing `title` parameter, or partial or substring matching beyond this one case. |
Totals from the same log: 3 turns, 7.5 s, estimated $0.072. Tokens: 6 fresh input, 653 output, 66380 read from cache, 14583 written to cache.
Cost, Turns and Denied Tools
With --output-format json the final result carries fields that every sample in this guide records. The ones that matter most:
| Field | What it tells you | Caveat |
|---|---|---|
num_turns | How many trips around the loop. The session above: 3 | More turns usually means more reading, not necessarily a better answer |
total_cost_usd | Claude Code's estimate for the run. The session above: $0.072 | Client-side estimate at list prices, not an invoice (Source 2) |
usage | Tokens: fresh input, output, and cache reads and writes | Cache reads are most of the input here; they are billed at a lower rate |
permission_denials | Tools Claude tried but was not allowed to run | An empty list does not prove nothing risky was attempted, only that nothing was blocked |
A real denial is worth looking at. In Recipe 1 (Chapter 16) Claude tried to read many files with one shell command (cat over a dozen files). The run was read-only with Bash not allowed, so it was denied and recorded:
The denial did not stop the run: the model was told no, and carried on with the Read tool. It is also a free audit trail. If you see a Bash denial you did not expect, find out why Claude wanted a shell.
"Explain What You Just Did"
Library prompt MET-03 asks Claude to describe its own steps. The same session was continued with --resume so the explanation refers to the real run above:
BookControllerTest.java, BookApiIntegrationTest.java and BookSearchTest.java. The cited BookSearchTest.java:21 is the test method, and the described assertions (200, two results, "Clean Architecture" then "Clean Code") match the file. It correctly says it changed no files and did not open the main source.One run agreeing with its log is not proof that it always will. A self-report is the model's account of its actions, written afterwards. The log is the record. For anything that matters, compare the two, as above, or use a hook that records tool calls yourself (Chapter 10).
A Reading Checklist
| Check | How |
|---|---|
| Did it read what it cites? | Open every file and line it names. Across the samples in Chapter 15, citations were mostly right and sometimes off by one line |
| What was verified versus assumed? | Add VER-03. A sample there (DBG-04) guessed code it had not opened |
| Did anything change? | git status and git diff. Read-only prompts should leave both empty |
| Was anything blocked? | Look at permission_denials |
| Is a claim measured or marketing-shaped? | "Noticeably faster" with no number is a guess (DOC-05 in Chapter 15) |
| Does the cost make sense? | A one-line question that used eight turns probably searched too widely: narrow the scope |
Key Takeaways, Exercises and Sources
- An answer is the end of a loop of turns. Tool calls are what happened; prose is a summary.
- Look at what it did not read. The sample session never opened the controller; its answer was about tests existing, not passing.
- Cost and turns are cheap signals of how widely Claude searched.
- Denials are an audit trail. Read them.
- A self-explanation is useful and checkable. Check it against the log for anything important.
Exercise 1 Beginner
Run any read-only question with claude -p "…" --output-format json and find num_turns, total_cost_usd and permission_denials in the output. Which surprised you?
Learning outcome: read the evidence fields.
Exercise 2 Intermediate
Repeat with --output-format stream-json --verbose. List the tool calls in order. Before you look at the answer, predict what it will say, then compare.
Learning outcome: connect tool calls to conclusions.
Exercise 3 Advanced
Resume the session with MET-03 and write down every claim in the explanation. Mark each one confirmed or not confirmed by the log. If any claim is not in the log, find out why.
Learning outcome: audit a self-report.
- Anthropic, How Claude Code works — the agentic loop, tools, turns.
- Anthropic, Manage costs — cost tracking and caching.
- Anthropic, Run Claude Code programmatically — output formats and
--resume.
The timeline and the resumed explanation are real, executed on 2026-10-31 (tools/capture_stream.sh; event log in prompts/samples/STREAM-01.timeline.json). The raw log is not published because its init event lists local configuration. Turn counts and costs come from that run only. The loop diagram is a simplification.