A prompt Claude can follow names four things: the task (what to do), the inputs (what to use), the output (what to produce), and the limits (what to avoid). When all four are present, Claude does the work you meant. When one is missing, Claude fills the gap with a guess, and the guess is the part you then have to fix.
This guide shows the four parts, then walks one weak prompt through a rewrite so you can see each part land.
Why do vague prompts fail?
Claude is good at following instructions and poor at reading minds. A request like "clean up this file" is four decisions disguised as one. Clean up which file? Reformat it, rename things, delete dead code, or all three? Leave the public API alone or not? Match an existing style? Claude picks an answer for each gap, acts on it, and you discover the mismatch only after the work is done.
The fix is a complete prompt, and a complete prompt is often shorter than the rambling version because it cuts hedging and states the decision directly. When a prompt still misfires, fixing a prompt that is not working walks through the usual culprits.
What does a good prompt include?
| Part | Question it answers | Example |
|---|---|---|
| Task | What action do you want | "Add input validation" |
| Inputs | What should Claude read or use | "to the form in src/checkout/form.ts" |
| Output | What should the result look like | "return typed errors, one per field" |
| Limits | What must Claude not do | "do not touch the submit handler" |
You do not need a template or labelled sections. You need all four facts present in plain sentences. Read your prompt back and check that each of the four is answerable. If one is not, Claude will answer it for you.
Part 1: the task
State the action as a verb on a specific thing. "Refactor", "add", "fix", "explain", "rename" are tasks. "Help me with the auth code" is not a task, it is a topic.
Weak: look at the login flow
Strong: find why the login flow rejects valid passwords and fix the cause
The strong version names the action (find, fix) and the target (the cause, not a symptom). Claude now knows when it is done.
Part 2: the inputs
Tell Claude what to read. In the Claude Code CLI, the precise way to do this is the @ file reference, which loads a specific file into context instead of making Claude search for it.
This loads exactly two files. Claude does not guess which file you mean and does not read forty unrelated ones. If you do not know the file, name the area and let Claude search:
Naming the inputs is the single highest-impact habit in prompting. Most failed prompts fail here: Claude worked on the wrong file because no file was named. For the deeper version of this idea, see context engineering.Common gotchaDescribing the file ("the settings file") instead of pasting the exact path feels close enough, but in a repo with three files that fit the description Claude opens the first plausible one and edits it.When you know the path, use the @ reference so there is nothing to guess; only fall back to "search the area" when you do not know where the code lives.
Part 3: the output
Describe the result you expect: its shape, its format, and where it goes. "Make it better" has no output. "Return a numbered list of issues, worst first, with the file and line for each" has a precise one.
| Output you want | How to say it |
|---|---|
| A code change | "edit the file in place, do not print the whole file back" |
| A review, no edits | "list problems as bullets, do not change any code" |
| A plan first | "outline the steps before writing code, wait for my go-ahead" |
| Structured data | "return JSON with keys id, status, reason" |
When you want machine-readable output from a scripted call, the CLI can enforce it. The --output-format json flag wraps the result as JSON so a script can parse it.
claude -p "List the exported functions in src/auth as JSON" --output-format jsonThe -p (short for --print) flag runs Claude once and prints the answer without entering interactive mode, which is what you want inside a script.
Part 4: the limits
Limits are the guardrails: what Claude must not touch, must not change, and must keep working. They are the part people skip, and skipping them is why a small request turns into a large diff.Common gotchaA vague limit like "don't break anything" is not followable, since Claude cannot tell what "broken" means for your code.Name the concrete thing to protect instead: which file, which signature, which behaviour stays exactly as it is.
Common limits worth stating:
- Scope: "only edit
src/checkout/, leave the rest alone." - Behaviour: "do not change the public function signatures."
- Style: "match the existing error-handling pattern in the file."
- Process: "do not run database migrations" or "do not commit."
That prompt has all four parts: task (add a retry), input (src/storage/upload.ts), output (three retries, one second apart), and limits (signature unchanged, no new dependency).
Before and after
Here is one prompt rewritten from a topic into an instruction. Watch each part get filled in.
Before
This is a topic, not a task. It has no named input (which file is the user settings code?), no defined output (reformat? rewrite? delete?), and no limits (is the saved-settings format safe to change?). Claude will pick answers for all four and probably reformat more than you wanted.
After
Now all four parts are explicit. Task: refactor for readability by splitting a function. Input: one named file. Output: smaller named functions, with a plan shown first. Limits: exports, signatures, and the file format are frozen, no other files, no new dependencies. Claude can follow this without guessing, and you can tell at a glance whether it did.
How the parts map to one instruction
The four parts are not a rigid order. Write them in whatever sentence order reads naturally. The test is presence, not position: can a reader answer all four questions from your prompt alone.
Where should I put rules that apply to every prompt?
Some limits are the same on every request: your style rules, your "never do this" list, the conventions of the project. Repeating them in each prompt wastes your effort and theirs. Claude Code reads a project memory file at the start of a session, so durable limits live there and apply to every turn automatically.
# Project rules
- Co-locate tests with source, as `<name>.test.ts`.
- Never edit files under `generated/`.
- Errors are typed; never throw bare strings.
- Ask before adding a dependency.With those rules loaded, your per-prompt limits shrink to the ones unique to the task. You can also push a rule into a single scripted call with --append-system-prompt, which appends text to Claude's system prompt for that run.
claude -p "Add a health check route to the API" --append-system-prompt "Return JSON only, never plain text."The split is simple: rules that are always true go in the memory file; limits specific to one task go in that task's prompt.
Common mistakes
| Mistake | What happens | The fix |
|---|---|---|
| No named input | Claude edits the wrong file | @-mention the file or name the folder |
| Task is a topic | Claude does something adjacent | State a verb and a target |
| No output shape | You get prose when you wanted a diff, or the reverse | Say "edit in place" or "list only, no edits" |
| No scope limit | A small ask becomes a large diff | "Only touch X, leave the rest" |
| Several tasks in one prompt | Claude half-does each | One task per prompt, or break it into steps and number them |
| Polite hedging | "maybe you could possibly look at" reads as optional | State the instruction plainly |
How do I check my prompt before sending it?
Read your prompt once and answer these four questions out loud. If any answer is "Claude will have to decide", fill that part in.
- Task: what verb, on what specific thing?
- Inputs: which files or area does Claude read?
- Output: what should the result be, and in what form?
- Limits: what must stay untouched?
This check takes a few seconds and removes the round trip where Claude does the wrong thing, you correct it, and it tries again. A prompt that passes the check is one Claude can follow on the first attempt.
What this is not
Naming four parts is not writing an essay. The shortest complete prompt is better than a long vague one. "Fix the failing test in @src/auth/session.test.ts, change the source not the test" is one sentence and has all four parts. Length is not the goal. Completeness is.
It is also not a script you recite. Once the four parts become a habit, you stop thinking about them as parts and write instructions that happen to be complete. The framework is training wheels for that habit, useful until the habit is automatic.