Advanced (Updated: 6/7/2026)

5 Advanced Techniques for When Claude Code Prompts Don't Work

When "just clean it up" makes Claude Code go off the rails, it's the request, not the model. Five techniques with Before/After examples.

5 Advanced Techniques for When Claude Code Prompts Don't Work

“Hey, refactor this component, make it nice.”

Thirty minutes after I threw that out, Claude Code had indeed refactored it. The naming was clean, too. The catch: it had also “helpfully” reordered the imports in the neighboring file I never asked it to touch, and my review diff had ballooned to 200 lines.

At first I blamed the model. “It keeps over-interpreting my instructions.” But after botching this enough times, I realized the truth. The model wasn’t the problem. The way I was asking was.

I already wrote up the fundamentals (specificity, context, output format, examples, iteration) in a separate post: 5 tips for better prompts. This article goes past that, narrowing in on advanced techniques that only matter the moment a prompt stops working in real work. Five of them: kill the ambiguity, hand over context by filename, make it verify in stages, lock the output format, and recover from failure. Every one of these I learned by crashing into it.

Key takeaways

  • Prompt accuracy is decided by fixing the boundaries, not by word choice. Write what may and may not change up front, and the diff stops running wild.
  • Don’t paste context into chat — hand it over by filename. “Read X first” is the single most effective line for stopping the model from writing on imagination.
  • Don’t make it do everything in one shot. Specify the order: read → plan → edit → verify → report. “Show me the plan first” alone slashes accidents.
  • Locking the output format (how diffs are shown, the shape of the report) makes review faster and cuts redo work.
  • On failure, don’t resend the same instruction. Hand over what you tried and what broke, and ask it to isolate the cause first.

You can confirm that Claude Code is an agent that reads your codebase, edits files, and runs commands in the official Claude Code overview. Because it’s an “AI that does work,” not an “AI that returns text,” the precision of your request maps directly onto your accident rate.

Technique 1: Kill “make it nice” — crush ambiguity with concrete prohibitions

The most common failure is handing over evaluation words as-is. “Make it nice,” “clean it up,” “do it properly,” “optimize this.” These work between humans, but to Claude Code they’re un-judgeable instructions. There’s no standard for what counts as “nice,” so the model moves on guesses. The instant it guesses, you get the 200-line accident from my intro.

What works is writing what you don’t want done with the same care as what you do want done. If you only state the allowed scope, it reads as “anything else is fair game.”

Before (vague, no boundaries):

Refactor this component to be nice, and tidy it up while you're at it.

After (with standards and boundaries):

Refactor src/components/UserCard.tsx to be more readable.

Do:
- Split any function over 60 lines into smaller ones by responsibility
- Fill in any missing prop types

Don't:
- Do not edit any file other than src/components/UserCard.tsx
- Do not make cosmetic-only changes like reordering imports
- Do not rename public props (it breaks the callers)

The key is the seemingly nitpicky prohibition like “don’t reorder imports.” My 200-line accident happened precisely because that one line was missing. Adding negatives isn’t about shackling the model — it’s about removing the room it has to step in “with good intentions.” The design for blocking overly broad deletes and production changes is also covered in Why “just do everything” is a forbidden phrase.

Technique 2: Don’t paste context into chat — hand it over by filename

Ever feel like the output was “written from imagination”? Calling a function that doesn’t exist, or reinventing a utility that’s already there. That’s usually because the context Claude Code needed never reached it.

A common move is pasting the whole reference snippet into chat. That tends to backfire. The moment you paste it, the context is frozen and drifts from the latest file, and the longer the paste, the more your actual instruction gets buried.

Instead, hand it over by filename and say “read this first.” Claude Code can open files itself, so it works after seeing the current contents.

Before implementing, read these in order first:

1. src/lib/api-client.ts (the existing fetch wrapper — you must use this)
2. src/features/orders/orderList.tsx (a similar list screen — match its structure and naming)
3. src/types/order.ts (type definitions — do not invent new types)

Then implement the order detail screen src/features/orders/orderDetail.tsx.
Use only the functions in api-client.ts; do not write your own fetch.

“Read this first” works because it forces the model to look at facts before writing on imagination. Adding “use exactly one similar implementation as the reference standard” makes the style and structure line up with existing code. Conversely, hand it ten reference files and it won’t know which to prioritize, melting time on exploration alone. The trick is narrowing the reading order and the standard it’s allowed to adopt.

By the way, the “always-honor-this” stuff that’s tedious to retype every time (build commands, naming rules, off-limits areas) goes in CLAUDE.md, not chat. The official Memory docs describe CLAUDE.md as context loaded every session. How to pick the granularity is split out into CLAUDE.md is decided by what you don’t write.

Technique 3: Don’t let it do everything in one shot — make it verify in stages

The smarter the model, the more it tries to sprint straight to the finish when you ask. That’s the trap: if a premise is off mid-run, you only get back the result of sprinting full-speed in the wrong direction. By the time you see the diff, it’s too late.

What works is an instruction that stops once before executing. The one I use most: “Show me the plan first. Don’t change any code until I say OK.” That single line alone dramatically cut wide-of-the-mark mega-rewrites.

Taking it further, split the work itself into stages.

Proceed in the following steps. After each step, stop once and wait for my "next."

Step 1: List the target files and any likely callers affected, and report as a list (do not edit yet)
Step 2: Present the functions you'll change and a brief bullet of why (do not edit yet)
Step 3: After approval, edit only within scope
Step 4: Run npm test and paste the result (PASS/FAIL) as-is
Step 5: Report changed files and any remaining concerns

If “stop at every step” feels like a hassle, make at least Step 1 mandatory. Just having it list the blast radius first lets you catch unexpected files getting mixed in early.

If you ask for verification “if you can,” it’ll be skipped without fail on a busy day. Write a concrete command name like npm test and make it paste the result. When it couldn’t run, having it report “what it couldn’t run” lets you make the call. I wrote up this “don’t take the self-report at face value” mindset in detail in Don’t trust Claude Code’s “done”.

Technique 4: Lock the output format to make review faster

Even for the same work, review slows down when the reporting is inconsistent every time. A reply like “mostly done, probably fine” just means you end up re-checking everything yourself.

Hand over the output format up front and it comes back at the same granularity every time. Review becomes “just read along the template,” and you miss less.

After the work, report using only the following format. No preamble or commentary.

## Changed files
- (list paths)

## What changed (one line per file)
- path: what changed and why

## Commands run and results
- command → PASS / FAIL (if FAIL, last 5 lines of the relevant log)

## Not yet verified
- (places to eyeball by hand, verifications that couldn't run)

When you ask for a code review, the output format matters even more. “Take an overall look” gets you an essay. Make it output a table that always includes severity, filename, line number, and a fix proposal, and it gets closer to a real-world review.

Field to specifyWhy write it
Severity (high/medium/low)Lets you decide fix order
Filename and line numberInstantly trace where it’s about
Reproduction conditionVerify whether it’s really a problem
Fix proposalDon’t leave it at “just flagging it”

Specifying the lens — like “prioritize security, data destruction, public API changes, and missing tests” — turns it from a list of thin nitpicks into a review that actually bites.

Technique 5: When it fails, don’t resend the same instruction

This is the most wasteful spot of all. When Claude Code’s output is underwhelming, you’re tempted to send the exact same prompt again. But if the input is nearly identical, so is the output. You’ll bang your head against the same wall forever.

The trick to recovering is to hand over, concretely, what the current state is and what’s broken, and ask it to isolate the cause instead of guessing.

Before (just resending):

It doesn't work. Fix it.

After (hand over state and symptoms, ask for isolation first):

After the last change, only the orderDetail test in npm test is failing.

- Failing test: "renders total price" in tests/orderDetail.test.ts
- Error: Expected "¥1,200" but received "1200"
- Recent change: the price-display formatting logic

Before fixing, explain 2-3 candidate causes, most-likely first.
Then fix it with the smallest possible diff. Do not delete the test.

Adding “before fixing, explain the candidate causes” stops the chain where Claude Code messes with the wrong place and breaks something else. People tend to jump to conclusions off just the last line of a failure log, so the more you organize and hand over the symptoms, the faster the recovery.

When it still won’t click, reset the context decisively. Drag a long conversation along and it tries to fix things while carrying the old, drifted premises. Handing a fresh session just the organized symptoms and the target files is often faster in the end.

Copy-paste ready: machine-check your prompt for “breakage”

Even when you’re conscious of the advanced techniques, in a rush you’ll forget to write the “off-limits scope” or the “verification command.” So I write the request into a file (prompt.md) and run a script to inspect whether the minimum items are present before I send it.

The following Node.js script checks that goal, scope, forbidden scope, verification command, and output format are all there. It runs as-is with no dependencies.

// check-prompt.mjs — detect gaps in a request before you send it
// Usage: node check-prompt.mjs prompt.md
import { readFileSync } from "node:fs";

const file = process.argv[2] || "prompt.md";
const text = readFileSync(file, "utf8");

// Codify the "without this, you crash" minimum conditions
const checks = [
  { ok: /(goal|objective|do:)/i.test(text), msg: "No goal (what to achieve)" },
  { ok: /(scope|may edit|target file)/i.test(text), msg: "No allowed scope" },
  { ok: /(do not|don't|never|forbidden)/i.test(text), msg: "No forbidden scope" },
  { ok: /(npm |pnpm |yarn |node |test|build|run)/i.test(text), msg: "No verification command" },
  { ok: /(report|output format|format|template)/i.test(text), msg: "No output format" },
];

const failed = checks.filter((c) => !c.ok);

if (failed.length > 0) {
  console.error(`Sending this as-is is accident-prone (${file}):`);
  for (const f of failed) console.error(`  - ${f.msg}`);
  process.exit(1);
}

console.log("OK: the key items are present. Looks safe to send.");

Running it is just this:

node check-prompt.mjs prompt.md

It’s only a few dozen lines, but when I crash during article rewrites or feature additions, it’s almost always the “off-limits scope” or the “verification command” that was missing. Just passing this before I send visibly cuts the redo work. Saving and templating requests that worked well is collected in Don’t throw away prompts that worked.

FAQ

Q. Do longer, more detailed prompts produce better accuracy? No. It’s structure over length. The official Memory docs also explain that longer instructions are harder to follow, while concrete and concise ones are easier to obey. Rather than rambling, dividing goal, scope, prohibitions, and verification with headings works better.

Q. Writing “don’t touch this” every time is tedious. Move the prohibitions common to every job (don’t touch the production DB, don’t add dependencies on a whim, etc.) into CLAUDE.md. Write the prohibitions specific to just this job in the request. Splitting where things live cuts duplication.

Q. Doesn’t stopping it in stages make things slower? For small, safe work, feel free to let it run in one shot. Staging pays off on changes whose blast radius is unclear, or work that ripples across multiple files. At minimum, keeping in the single line “show me the plan first” keeps you safe.

Q. When I hand over an example (a model snippet), it copies it verbatim, which is a problem. The cause is mixing examples and constraints. Spell out the role: “use this file only as a reference for structure and naming; don’t copy the actual logic.” Writing separately what you want imitated and what boundary you want honored gets you the intended result.

Q. If I write “absolutely never do X” in CLAUDE.md, will it always stop? It won’t. CLAUDE.md is treated as context, not enforcement. For operations you truly want stopped (deletes, production changes, etc.), mechanically blocking them with the officially documented PreToolUse hook is the reliable route.

What I actually tried

After the 200-line accident in the intro, I stopped polishing the “phrasing” of my prompts. What I did instead was add two lines to the top of every request: “Don’t touch” and “verification command.” That alone took accidents where unexpected files got mixed in to nearly zero.

The thing that worked best is Technique 3’s “show me the plan first.” Since making it a verbal tic, time stolen by wide-of-the-mark mega-rewrites has plummeted. Claude Code, being smart, runs at full speed — so making it pause once before it starts running is, in the end, the fastest path. That’s my honest read right now.

For all the talk of “advanced techniques,” all I’m doing is “killing the ambiguity, fixing the boundaries, and making it verify.” Start with your next task by adding a single “don’t touch” line to your request. Once you’ve accumulated patterns you reuse, take a look at the training and consultation page and the materials and templates list, too.

#Claude Code #prompts #advanced prompting #AI instructions #verification
Free

Free PDF: Claude Code Cheatsheet

Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.

We handle your data with care and never send spam.

Level up your Claude Code workflow

Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.

Masa

About the Author

Masa

Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.