Claude · 16 · Part 8 · Hands-On Prompts

Prompt Recipes

A single prompt is a sentence. A recipe is a few of them in an order that works for one common job: understanding a new repository, planning a change safely, debugging from evidence, reviewing a diff, or learning a stack from one you know. Each recipe below was run through Claude Code on a real project, and the result is shown with an honest check. At the end is a builder that lets you assemble your own prompt from the library.

5
Recipes
5
Real runs
1
Prompt builder
Information current as of: 2026-10-31. Recipes ran with Claude Code 2.1.314 and model claude-sonnet-5-5 against the bookshelf project, read-only (Read, Grep, Glob; at most 8 turns and $0.50 each).
01
Composition

Why Order Matters

The blocks from Chapter 15 can go in any order, but a reliable pattern has emerged in the recipes below. This is the author's pattern, not an Anthropic rule. Anthropic's pages recommend the same ingredients (specific scope, a way to verify, plan before code) without prescribing an order (Source 1).

The usual order of a recipe
1 Limitsread only, plan 2 Contextaudience, role 3 Taskthe actual ask 4 Formattable, steps 5 Checkproof, not prose if the check fails, tighten the limits and run again
  • Limits first, because they are the instructions you least want Claude to miss.
  • The check last, so it is the freshest thing in the prompt when Claude writes its answer.
  • Same blocks, different jobs. Recipe 1 and Recipe 4 are both read-only; what changes is the task block and the format block.
A caveat about "wait for my approval". In Recipe 2 the block CTL-02 asks Claude to wait. These samples ran non-interactively (claude -p), where there is nobody to reply, so the run simply ended after the plan. In an interactive session you would read the plan and answer. The result is the same safe state: nothing changed.
02
Five Real Runs

The Recipes

Understand an unfamiliar repository R-01

Situation: First day on a codebase you did not write.

BlockWhat it contributes
EXP-01Codebase overview
AUD-01Like a novice developer
EXP-04Riskiest parts
VER-03Verified vs assumed

Why this order: EXP-01 gives the map, AUD-01 turns it into plain words, EXP-04 shows where the danger is, VER-03 separates what Claude checked from what it assumed. Read-only is already built into EXP-01 and EXP-04.

The composed prompt
Give me an overview of this codebase: its purpose, main folders, entry points and how to run it. Read only. Explain how this project works like I'm a novice developer. What are the riskiest or most confusing parts of this code for a new team member? Rank them. Read only. List what you verified yourself and what you are only assuming.
Real sample: what Claude answered (Checked)
Prompt as sent
Give me an overview of this codebase: its purpose, main folders, entry points and how to run it. Read only. Explain how this project works like I'm a novice developer. What are the riskiest or most confusing parts of this code for a new team member? Rank them. Read only. List what you verified yourself and what you are only assuming.
Actual output · executed 2026-10-31 · claude-sonnet-5-5 · Claude Code 2.1.314 · 21 turns · 39.0s · est. $0.168 · project commit f23d2f5
# Bookshelf overview ## 1. Overview **Purpose:** a small REST API for a book catalogue. It is a Spring Boot 4.1.2 app on Java 21, built with the Maven wrapper. It stores data in an in-memory H2 database. **Main folders** - `src/main/java/com/example/bookshelf/` holds all the application code in one flat package. - `src/main/resources/` holds `application.properties`, which contains only the app name. - `src/test/java/...` holds 5 test classes. - `scripts/` holds `verify.sh` and `status.sh`. - `.claude/` holds agent tooling: settings, a block-destructive hook, a sql-reviewer agent and a verify-build skill. - `.github/workflows/claude-review.yml` runs tests on pull requests, then an AI review. - `feature_list.json`, `.mcp.json`, and the untracked `mcp/` and `.claude/skills/explain-endpoint/` are supporting files. - `target/` is build output. **Entry points** - `BookshelfApplication` is the `main` class. - `BookController` serves `/api/books`: list, `/search?title=`, `/{id}` and POST. - `StatsController` serves `GET /api/stats`. - `DataSeeder` runs at startup and inserts 3 authors and 6 books. **How to run** (from `CLAUDE.md`) - Start the app with `./mvnw spring-boot:run`. It listens on port 8080. - Run all tests with `./mvnw -B test`. - Run one test class with `./mvnw -B test -Dtest=BookControllerTest`. ## 2. How it works, for a novice Think of a restaurant. - **Controller** is the waiter. It takes the HTTP request, such as `GET /api/books/3`, and passes it on. It does no real work. - **Service** is the kitchen. `BookService` holds the logic: find books, search by title, or create a book. - **Repository** is the pantry. `BookRepository` talks to the database. Spring writes the SQL for you from method names like `findByTitleContainingIgnoreCaseOrderByTitle`. - **Entity** (`Book`, `Author`) is a Java class that maps to a database table. One author has many books. - **DTO** (`BookDto`) is the plate that goes to the customer. The API returns this shape, never the raw entity. - **Validation:** `CreateBookRequest` rejects blank titles or authors, and years outside 1450–2100. - **Errors:** if a book isn't found, `ApiExceptionHandler` turns the exception into a standard 404 response. - **Creating a book:** the service looks up the author by name and creates one if missing. It then saves the book. - **Data lifetime:** the database lives in memory, so everything resets on restart. The seeder refills the sample data each time. ## 3. Riskiest or most confusing parts, ranked 1. **The one-query rule (`BookQueryCountTest`).** `Book.author` is `LAZY`, so listing books would normally fire one extra query per book (the "N+1" problem). The `@EntityGraph` on the repository methods fixes this. If someone adds a new repository method without it, or touches the mapping, the test fails with a confusing count. Any new method that returns books with authors needs the same annotation, or it silently becomes slow. 2. **Duplicate authors and no uniqueness constraint.** `create` does "find by name, else insert" with no unique constraint on `Author.name`. Two simultaneous requests for the same new author can create duplicates. Trailing spaces or different capitalisation also produce separate authors. `AuthorRepository` was not read, so I'm inferring that `findByName` returns an Optional. 3. **Thin error handling.** `ApiExceptionHandler` handles only `BookNotFoundException`. Validation failures fall back to Spring's default handling. `CLAUDE.md` says to add new exceptions there, so the handler will keep growing. A non-numeric `/{id}` also relies on framework defaults. 4. **In-memory H2 with no config.** `application.properties` is nearly empty, so the schema, IDs and connection all come from Spring Boot defaults. Nothing persists, and moving to a real database means changing settings that don't exist yet. Hibernate's `@GeneratedValue` with no strategy specified also surprises people. 5. **Agent tooling around the code.** Several guardrails live outside the app and are easy to overlook: - A `Stop` hook runs the full test suite every time the agent stops. - The `block-destructive.sh` hook only pattern-matches a few strings with grep. It is easy to bypass and could block harmless commands. - `verify.sh` caps a change at 20 files against `main`. - CI sends pull requests to an AI reviewer that needs an `ANTHROPIC_API_KEY` secret. - `.mcp.json` points at `issues.example.com`, a placeholder that likely doesn't work. 6. **Flat package and minor inconsistencies.** Everything sits in one package. `StatsController` skips the service layer and uses the repositories directly, which breaks the controller → service pattern. `BookDto.from` is used for mapping. 7. **Conventions that aren't enforced.** The rule about `publication_year` (H2 rejects `year` as a column name) lives only in a comment and `CLAUDE.md`. ## 4. What I verified and what I'm assuming **Verified by reading the files** - `CLAUDE.md`, `pom.xml`, `application.properties`, `BookController`, `BookService`, `BookRepository`, `Book`, `Author`, `DataSeeder`, `StatsController`, `ApiExceptionHandler`, `CreateBookRequest`, `BookQueryCountTest`, `verify.sh`, `.claude/settings.json`, `block-destructive.sh`, `claude-review.yml` and `.mcp.json`. - The tracked file list and the top-level directory listing, from a `git ls-files` and `ls` run I did before Bash was denied. - The endpoints, the seed data, the `@EntityGraph` mitigation, the 1450–2100 year range, the 20-file budget and the Java 21 and Boot 4.1.2 versions. **Assumed, not verified** - That the app starts and the tests pass. I ran nothing, so no build or test result is confirmed. - That port 8080 is correct and that H2 is the auto-configured database. This comes from `CLAUDE.md` and the dependencies, not from observed behaviour. - The contents of `BookDto`, `AuthorRepository`, `BookNotFoundException`, `BookshelfApplication`, `scripts/status.sh`, `feature_list.json`, the 5 test classes other than `BookQueryCountTest`, `.claude/agents` and `.claude/skills`. I haven't opened them, and I didn't look inside the untracked `mcp/` or `.claude/skills/explain-endpoint/`. - The race-condition claim about duplicate authors. It follows from the code but I didn't test it. - That validation errors come back in Spring's default format. I didn't check whether another handler exists. - That `issues.example.com` is a placeholder, based on the domain name.
Author's check: Checked. Overview matches the repository layout it read (flat package, five test classes, .claude folder, scripts, workflow). It read many files in a single Bash call, which is why one turn lists a long command.

Plan a safe change R-02

Situation: You want to add something and you want to approve the plan before any file changes.

BlockWhat it contributes
your wordsYour own line: “I want to add a DELETE /api/books/{id} endpoint to this project.”
THK-01List assumptions
CTL-04Stay in scope
CTL-02Plan, then wait
VER-01Show the evidence

Why this order: A context line says what you want; THK-01 surfaces assumptions; CTL-04 keeps the diff small; CTL-02 makes Claude stop and wait; VER-01 says how the result must be proven.

The composed prompt
I want to add a DELETE /api/books/{id} endpoint to this project. List your assumptions before you answer. Change only the controller, the service and the tests. If another file needs to change, stop and tell me why. Before you change anything, tell me your plan and wait for my approval. Run ./mvnw -B test and show me the command and its output as evidence.
Real sample: what Claude answered (Checked)
Prompt as sent
I want to add a DELETE /api/books/{id} endpoint to this project. List your assumptions before you answer. Change only the controller, the service and the tests. If another file needs to change, stop and tell me why. Before you change anything, tell me your plan and wait for my approval. Run ./mvnw -B test and show me the command and its output as evidence.
Actual output · executed 2026-10-31 · claude-sonnet-5-5 · Claude Code 2.1.314 · 6 turns · 12.2s · est. $0.089 · project commit f23d2f5
## Assumptions 1. A successful `DELETE /api/books/{id}` returns **204 No Content** with no body. 2. An unknown id returns **404**. It reuses `BookNotFoundException`, which `ApiExceptionHandler` already maps to a ProblemDetail with the message "Book N not found". That means I don't need to touch the handler. 3. Only the `Book` row is deleted. The `Author` row stays, because other books may reference it, and I'm not adding orphan cleanup. 4. `BookRepository` extends `JpaRepository<Book, Long>`, so `existsById` and `deleteById` are available without editing it. I haven't opened that file yet, so this is unconfirmed. 5. There is no auth, soft-delete or audit requirement. 6. Existing tests don't depend on the seeded book count in a way a delete would break. 7. `./mvnw -B test` runs offline, or the dependencies are already cached. ## Plan **`BookService.java`**: add a transactional method. ```java @Transactional public void delete(long id) { if (!books.existsById(id)) { throw new BookNotFoundException(id); } books.deleteById(id); } ``` **`BookController.java`**: add the endpoint, plus the `DeleteMapping` import. ```java @DeleteMapping("/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) public void delete(@PathVariable long id) { service.delete(id); } ``` **Tests**, in `BookControllerTest.java` (mocked service): - `deleteReturns204`: the service is called and the response is 204. - `deleteUnknownIdReturns404`: the service throws `BookNotFoundException(99L)`, so the response is 404 with detail "Book 99 not found". I'd also add a delete-then-GET-returns-404 case to `BookApiIntegrationTest.java`. I haven't read that file yet. If it doesn't fit the existing style, I'll keep to the controller test. **Verification**: run `./mvnw -B test` and show you the command and its output. **Stop condition**: if a change turns out to be needed outside those three files, such as a repository method or the exception handler, I'll stop and tell you why. I won't make the change. I haven't changed anything. Do you approve this plan?
Author's check: Checked. It stopped at the plan and changed nothing (the bookshelf working tree stayed clean). It admitted that it had not opened BookRepository, so the existsById assumption was unconfirmed. That is the behaviour CTL-02 and THK-01 are meant to produce.

Debug from a stack trace R-03

Situation: You have an error and no idea where to start.

BlockWhat it contributes
DBG-01Hypotheses, not fixes
your wordsYour own line: “Check each hypothesis against the project files before you rank it.”
DBG-06Cause, not symptom

Why this order: DBG-01 forces hypotheses before fixes, a context line tells Claude to check them against the real files, and DBG-06 pushes past the symptom to the cause.

The composed prompt
Here is the error: com.example.bookshelf.BookNotFoundException: Book 99 not found at com.example.bookshelf.BookService.lambda$findById$0(BookService.java:25) at com.example.bookshelf.BookService.findById(BookService.java:25) at com.example.bookshelf.BookController.get(BookController.java:31) (This was returned to the client as an HTTP 500 for GET /api/books/99.) Give me 3 hypotheses ranked by likelihood and say how to test each one. Don't fix anything yet. Check each hypothesis against the project files before you rank it. Find the root cause, not just the symptom. Explain the difference between them in one sentence.
Real sample: what Claude answered (Checked)
Prompt as sent
Here is the error: com.example.bookshelf.BookNotFoundException: Book 99 not found at com.example.bookshelf.BookService.lambda$findById$0(BookService.java:25) at com.example.bookshelf.BookService.findById(BookService.java:25) at com.example.bookshelf.BookController.get(BookController.java:31) (This was returned to the client as an HTTP 500 for GET /api/books/99.) Give me 3 hypotheses ranked by likelihood and say how to test each one. Don't fix anything yet. Check each hypothesis against the project files before you rank it. Find the root cause, not just the symptom. Explain the difference between them in one sentence.
Actual output · executed 2026-10-31 · claude-sonnet-5-5 · Claude Code 2.1.314 · 12 turns · 32.1s · est. $0.146 · project commit f23d2f5
I haven't found a cause in the current source yet. The current code turns this exception into a 404, so the 500 has to come from somewhere else. I haven't run anything, and I changed nothing. ## What the project files show - `ApiExceptionHandler` is a `@RestControllerAdvice` with `@ExceptionHandler(BookNotFoundException.class)`. It returns a `ProblemDetail` with status 404. It was added in `c12f41d`, before the search commit. - `BookControllerTest.unknownIdReturns404` asserts a 404 for `GET /api/books/99`. It passes in `target/surefire-reports`, but it uses a mocked service, so it doesn't prove the real app returns 404. - `BookApiIntegrationTest` never requests a missing id. The real stack is untested for this case. - The trace's line numbers (`BookService:25`, `BookController:31`) don't match HEAD (30 and 37). The offsets are 5 and 6, which is exactly what the search commit `992cb18` added. So the trace came from a build made before `992cb18`. - There is no security, filter or config class that could intercept the exception. `application.properties` only sets the application name. ## Ranked hypotheses **1. The process that served the request was running a stale or different build (most likely).** - **Evidence:** The line offsets match the commit before `992cb18`. HEAD's code can't produce a 500 here, and the handler has been in the source since before that commit. - **Caveat:** The handler existed in `992cb18^` too, so "old build" alone doesn't explain the 500. The old build would also have to lack the handler or have it fail to register. For example, it could be a jar or `target/classes` that was only partly recompiled, or a different deployment. - **Test:** 1. Identify the running jar or process and its build time. 2. Rebuild with `mvn clean package`, restart, and run `curl -i localhost:8080/api/books/99`. 3. A 404 means the old build was the problem. 4. To confirm, check out `992cb18^`, build, run the same request, and see whether it gives a 500. **2. The handler isn't registered or doesn't match in the running app (component scan or a handler-method issue).** - **Evidence:** The `@WebMvcTest` slice picks up `@RestControllerAdvice`, so the unit test would pass even if the full app didn't register it. The handler method is package-private, which Spring allows, but that is the only unusual thing about it. - **Test:** 1. Start the real app and request `/api/books/99`. 2. Turn on `logging.level.org.springframework.web.servlet.mvc.method.annotation=DEBUG`. It will show whether `ApiExceptionHandler` resolves the exception. 3. Add a real-stack test with `@SpringBootTest` and MockMvc that requests a missing id and asserts a 404. **3. Something rewrote the status after the handler ran (a proxy, gateway or client wrapper).** - **Evidence:** The "HTTP 500" was reported second-hand ("returned to the client"). The trace is the server-side log, which would still show the exception being thrown even if the handler turned it into a 404. The project has no gateway code, so I can't confirm this from the files. - **Test:** Call the app directly with `curl -i`, bypassing any proxy or client, and compare the status. Check the server log for `Resolved [BookNotFoundException]`. That line means the handler ran. ## Root cause vs symptom The symptom is the 500 on `/api/books/99` and the stack trace. The root cause is whatever made that running process not apply the 404 mapping that the source defines. The missing book is only the trigger. My working theory is that the process was running an older build. I'd need the actual running build or a real-stack request to confirm it, and I can do that next if you want.
Author's check: Checked. The stack trace in this prompt was deliberately a made-up 'report' of an old bug. Claude noticed the current code returns 404, said it had found no cause, and did not invent one. A good result for a prompt with stale evidence; it shows why DBG-01 asks for hypotheses, not a fix.

Review a change R-04

Situation: Before merging a feature you or an agent wrote.

BlockWhat it contributes
ROL-01Strict reviewer
FMT-01As a table
VER-03Verified vs assumed

Why this order: ROL-01 sets the reviewer stance (and tells it to skip style), FMT-01 makes the findings comparable in a table, VER-03 exposes what the review did not check.

The composed prompt
Act as a strict code reviewer. Review the title search feature (the search code in BookController, BookService and BookRepository) for correctness and security. Skip style. If you find nothing important, say so. Answer as a table with the columns: finding, file and line, failing scenario, severity. List what you verified yourself and what you are only assuming.
Real sample: what Claude answered (Partly correct)
Prompt as sent
Act as a strict code reviewer. Review the title search feature (the search code in BookController, BookService and BookRepository) for correctness and security. Skip style. If you find nothing important, say so. Answer as a table with the columns: finding, file and line, failing scenario, severity. List what you verified yourself and what you are only assuming.
Actual output · executed 2026-10-31 · claude-sonnet-5-5 · Claude Code 2.1.314 · 5 turns · 15.0s · est. $0.088 · project commit f23d2f5
I found nothing important: no SQL injection and no correctness bug. There are two low-severity robustness gaps. | Finding | File and line | Failing scenario | Severity | |---|---|---|---| | Blank or empty `title` matches every row. `@RequestParam String title` accepts `""` and `" "`. | `BookController.java:31`, `BookService.java:25` | `GET /api/books/search?title=` returns the whole table, so it behaves like `list()`. A client that sends an empty search box gets everything and may read that as a bug. | Low | | The result set is unbounded: no `Pageable`, no limit, and no cap on `title` length. | `BookRepository.java:13`, `BookController.java:31` | On a large table, a search for `a` loads every matching `Book` and its `Author` into memory and serializes them all. The `LIKE '%x%'` pattern also can't use an index, so each call is a full scan. That makes it cheap to abuse for resource exhaustion. | Low | **What I verified myself, by reading the three files:** - The search is a derived query, `findByTitleContainingIgnoreCaseOrderByTitle(String)`. There is no `@Query`, no string concatenation and no native SQL, so there is no SQL injection path in this code. - `@EntityGraph(attributePaths = "author")` fetches the author eagerly. `BookDto.from` reads `getAuthor().getName()`, and the service method is `@Transactional(readOnly = true)`. I see no N+1 queries and no lazy-loading failure. - The `title` parameter is required, so a missing one returns 400 instead of passing null to the repository. - A search with no matches returns an empty list. **What I'm assuming and did not check:** - **Wildcard escaping:** I believe Spring Data JPA's `Containing` keyword escapes `%` and `_` in the input, so `title=%` matches only a literal percent sign. I did not run it to confirm. - **Case matching:** I did not check that `IgnoreCase` handles non-ASCII titles correctly on your database, such as Turkish `İ`. That depends on the database. - **Authentication and rate limiting:** I did not look for Spring Security or other config, so I don't know whether the endpoint is public or rate-limited. That affects how serious the unbounded result set is. - **Tests:** I did not run the build or the tests, and I did not look at the existing search tests. - **Rest of the codebase:** I did not read `Book.java`, `Author` or the exception handlers, so I can't say whether the entity mapping or error responses leak anything.
Author's check: Partly correct. Two low-severity findings (blank title matches everything; unbounded results) are plausible and consistent with the code. It did not run the app, so the behaviour is read from source, not reproduced.

Learn a new framework from what you know R-05

Situation: You are fluent in one stack and new to another.

BlockWhat it contributes
AUD-03Map to what I know
LRN-02Three steps with exercises

Why this order: AUD-03 bridges from the stack you know and makes Claude say where the analogy breaks; LRN-02 turns the answer into a short guided lesson.

The composed prompt
I know Python and Flask well but Java and Spring Boot not at all. Explain how a request becomes a method call in this project by mapping it to what I already know, and say where the analogy breaks. Teach me how Spring Boot routes an HTTP request to a controller method in 3 steps, with one small exercise after each. Wait for me to answer before continuing.
Real sample: what Claude answered (Checked)
Prompt as sent
I know Python and Flask well but Java and Spring Boot not at all. Explain how a request becomes a method call in this project by mapping it to what I already know, and say where the analogy breaks. Teach me how Spring Boot routes an HTTP request to a controller method in 3 steps, with one small exercise after each. Wait for me to answer before continuing.
Actual output · executed 2026-10-31 · claude-sonnet-5-5 · Claude Code 2.1.314 · 3 turns · 10.2s · est. $0.075 · project commit f23d2f5
## Step 1: Registering routes (`@RestController` + `@RequestMapping` + `@GetMapping`) In Flask you register routes by hand: ```python bp = Blueprint("books", __name__, url_prefix="/api/books") @bp.get("/<int:id>") def get(id): ... ``` `BookController.java` says the same thing with annotations: | Flask | This project (`BookController.java`) | |---|---| | `Blueprint(..., url_prefix="/api/books")` | `@RequestMapping("/api/books")` on the class (line 16) | | `@bp.get("/<int:id>")` | `@GetMapping("/{id}")` (line 35) | | `@bp.post("/")` | `@PostMapping` (line 40) | | Blueprint is a module-level object | `@RestController` marks the class as a bean that Spring should scan and register (line 15) | At startup Spring scans the classpath for classes with `@RestController`. It reads every mapping annotation and builds a table of (HTTP method, path pattern) → Java method. That table is your `app.url_map`. **Where the analogy breaks:** - You never call `app.register_blueprint(...)`. Component scanning finds the class by itself, so nothing in your code mentions `BookController` as a route. - The path variable's type comes from the method parameter (`long id`), not from the URL pattern. `{id}` has no converter like `<int:id>`. - `@GetMapping` with no path means "the prefix itself", so `list()` serves `GET /api/books`. ### Exercise 1 Using `BookController.java`, answer these: 1. Which method handles `GET /api/books/42`, and which handles `GET /api/books/search?title=dune`? 2. `/search` and `/{id}` could both match `/api/books/search`. Flask has the same problem. Based on what you know of routing, how do you expect Spring to resolve it? Guess before you look anything up. Reply with your answers and I'll move on to step 2, where the request is turned into method arguments.
Author's check: Checked. The cited lines for @RequestMapping (16), @GetMapping (35), @PostMapping (40) and @RestController (15) match the file at the captured commit.
03
Build Your Own

The Prompt Builder

Pick a recipe to start from, or add blocks one by one. Edit any line, reorder, and fill the {placeholders}. The text at the bottom is your prompt. Everything runs in your browser; nothing is sent anywhere.

Your prompt
Limitation. The builder only joins text. It cannot tell whether your blocks contradict each other (for example "read only" together with "fix it"). Read the result once before you send it.
04
Summary

Key Takeaways, Exercises and Sources

∑ Prompt recipes: what to remember
  • A recipe is blocks in an order: limits, context, task, format, check.
  • Stale evidence gets an honest answer if you ask for hypotheses. In Recipe 3 the pasted stack trace no longer matched the code; Claude said so instead of inventing a cause.
  • Plan-first prompts are cheap insurance. Recipe 2 changed nothing and listed an assumption it had not verified.
  • Read-only reviews read the source, they do not run the app. Reproduce a finding before you act on it.
  • Write down recipes that work for your own repository, with the blocks and fills you used.
Exercises

Exercise 1 Beginner

Load Recipe 1 in the builder, replace the first line with your own project's description, and run it read-only on a repository you did not write. Note one thing in the answer you did not know.

Learning outcome: use a recipe on unfamiliar code.

Exercise 2 Intermediate

Build a recipe for a job you do every week (for example "summarise a pull request for a non-technical reader"). Run it three times. Which block changed the answer most? Remove it and compare.

Learning outcome: learn what each block is worth.

Exercise 3 Advanced

Take Recipe 3 and feed it a stack trace that does match your current code. Then feed it one that is slightly wrong on purpose (a different line number). Record whether Claude notices, and how it says so.

Learning outcome: test how a recipe behaves with bad evidence.

Sources (read on 2026-10-30; paraphrased)
  1. Anthropic, Best practices for Claude Code — give Claude a way to verify, explore and plan before coding, be specific.
  2. Anthropic, Permission modes — plan mode and non-interactive behaviour.
  3. Anthropic, Run Claude Code programmatically — claude -p and its limits flags.

Recipes R-01 to R-05 were executed on 2026-10-31 (tools/capture.sh, results in prompts/samples/). The stack trace in R-03 was deliberately an old, no-longer-valid report. The ordering advice is the author's own pattern.