Skip to content
AI Dev Toolkit.
Esc
  • AI Token CounterCount tokens for GPT, Claude, Gemini, DeepSeek, Qwen and more.Tool
  • LLM API Cost CalculatorEstimate per-request, daily and monthly API costs.Tool
  • AI Model ComparisonCompare prices, context windows and features across models.Tool
  • AI Model Pricing PagesSpecs, real costs and cheaper alternatives for popular models.Tool
  • Context Window CheckerSee whether your text fits each model’s context window.Tool
  • Subscription vs API CalculatorFind out whether a chat plan or the API is cheaper for you.Tool
  • GPU / VRAM CalculatorCheck how much VRAM a local model needs and which GPUs fit.Tool
  • Prompt Caching CalculatorEstimate savings from prompt caching.Tool

Prompt template · Code

Code review prompt template

Review a diff for bugs, risky changes and missing tests, ranked by severity with line references. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.

294 tokens unfilled · 471 with the example below · o200k_base (GPT-4o and later)

Template

The prompt

Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.

Prompt (one message, plain text)
You are a senior {{language}} engineer reviewing a pull request for a teammate. You care about correctness first, then security, then maintainability.

<context>
What the change is meant to do:
<intent>
{{intent}}
</intent>

The diff, in unified format:
<diff>
{{diff}}
</diff>
</context>

<constraints>
- Only comment on lines the diff adds or changes. Unchanged code is context, not a target.
- Report real problems: bugs, unhandled errors, security issues, race conditions, breaking API changes and missing tests for new behaviour. Skip style points a formatter or linter would catch.
- If you can’t tell whether something is a bug without code you can’t see, say what you would check instead of guessing.
- If the diff has no blocking problems, say so plainly. An empty review is a valid result.
</constraints>

<output_format>
A numbered list, most serious first. For each finding:
- Severity: blocker, should fix, or question
- Where: file and line from the diff
- Problem: one or two sentences
- Fix: a concrete change, with a short code snippet if it helps

End with one sentence on whether the change does what its intent says.
</output_format>

<task>
Review the diff against its stated intent. Find the problems a careful reviewer would block or question before merging, and say how to fix each one.
</task>
For an API call: system prompt and user message

With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.

System prompt
You are a senior {{language}} engineer reviewing a pull request for a teammate. You care about correctness first, then security, then maintainability.

<constraints>
- Only comment on lines the diff adds or changes. Unchanged code is context, not a target.
- Report real problems: bugs, unhandled errors, security issues, race conditions, breaking API changes and missing tests for new behaviour. Skip style points a formatter or linter would catch.
- If you can’t tell whether something is a bug without code you can’t see, say what you would check instead of guessing.
- If the diff has no blocking problems, say so plainly. An empty review is a valid result.
</constraints>

<output_format>
A numbered list, most serious first. For each finding:
- Severity: blocker, should fix, or question
- Where: file and line from the diff
- Problem: one or two sentences
- Fix: a concrete change, with a short code snippet if it helps

End with one sentence on whether the change does what its intent says.
</output_format>
User message
<context>
What the change is meant to do:
<intent>
{{intent}}
</intent>

The diff, in unified format:
<diff>
{{diff}}
</diff>
</context>

<task>
Review the diff against its stated intent. Find the problems a careful reviewer would block or question before merging, and say how to fix each one.
</task>

Variables

What to put in each variable

{{language}}
The main language of the change, such as TypeScript or Go. It sets the reviewer’s expertise.
{{intent}}
One to three sentences on what the change should do, usually the ticket or PR summary. Without it the model can only review style.
{{diff}}
The output of git diff or the PR’s patch. Unified format keeps file names and line numbers, which the output refers back to.

Use

When to use it

Use it as a first pass before a human review, or on your own branch before you open the pull request. It works best on focused diffs of a few hundred lines, where every changed line fits comfortably in the context with room to reason about it.

It isn’t a replacement for a reviewer who knows the codebase. The model only sees the diff and what you tell it, so it can’t know that a helper already handles a case, or that a config flag changes behaviour in production. Treat its findings as questions to check, not verdicts.

Structure

Why it’s structured this way

The intent comes before the diff because a review is a comparison: does this code do what it claims? Without the intent, models fall back to generic advice about naming and comments. Both go in the context section, so the long material sits above the instruction, which is where Anthropic’s long-context guidance and Google’s Gemini guide both say it belongs.

The constraints narrow the job. “Only comment on changed lines” stops the model reviewing the whole file. Ruling out linter-level style points removes the noise that makes AI reviews tiring to read. The rule about unseen code gives the model a way to be honest instead of inventing what a function does, and saying that an empty review is fine stops it padding the list to look useful.

The output format makes findings sortable and checkable. A severity label lets you triage, the file and line let you jump to the code, and the final sentence about intent catches the case where every line is fine but the change does the wrong thing.

Example

A filled-in example

{{language}}
TypeScript
{{intent}}
Retry failed webhook deliveries up to three times with exponential backoff, then mark the delivery as failed.
{{diff}}
--- a/src/webhooks/deliver.ts
+++ b/src/webhooks/deliver.ts
@@ -12,9 +12,20 @@ export async function deliver(hook: Webhook, payload: unknown) {
-  const res = await fetch(hook.url, { method: "POST", body: JSON.stringify(payload) });
-  if (!res.ok) await markFailed(hook.id);
+  let attempt = 0;
+  while (attempt <= 3) {
+    const res = await fetch(hook.url, { method: "POST", body: JSON.stringify(payload) });
+    if (res.ok) return;
+    await sleep(2 ** attempt * 1000);
+    attempt++;
+  }
+  await markFailed(hook.id);
 }

What to look for. A good review of this diff should notice that a network error from fetch throws out of the loop, so the delivery is never retried or marked as failed, and that the loop sleeps 8 seconds after the last attempt before giving up. It might also question retrying 4xx responses that will never succeed. Each finding is a gap between the code and the stated intent.

The complete filled-in prompt (471 tokens)
Filled-in prompt
You are a senior TypeScript engineer reviewing a pull request for a teammate. You care about correctness first, then security, then maintainability.

<context>
What the change is meant to do:
<intent>
Retry failed webhook deliveries up to three times with exponential backoff, then mark the delivery as failed.
</intent>

The diff, in unified format:
<diff>
--- a/src/webhooks/deliver.ts
+++ b/src/webhooks/deliver.ts
@@ -12,9 +12,20 @@ export async function deliver(hook: Webhook, payload: unknown) {
-  const res = await fetch(hook.url, { method: "POST", body: JSON.stringify(payload) });
-  if (!res.ok) await markFailed(hook.id);
+  let attempt = 0;
+  while (attempt <= 3) {
+    const res = await fetch(hook.url, { method: "POST", body: JSON.stringify(payload) });
+    if (res.ok) return;
+    await sleep(2 ** attempt * 1000);
+    attempt++;
+  }
+  await markFailed(hook.id);
 }
</diff>
</context>

<constraints>
- Only comment on lines the diff adds or changes. Unchanged code is context, not a target.
- Report real problems: bugs, unhandled errors, security issues, race conditions, breaking API changes and missing tests for new behaviour. Skip style points a formatter or linter would catch.
- If you can’t tell whether something is a bug without code you can’t see, say what you would check instead of guessing.
- If the diff has no blocking problems, say so plainly. An empty review is a valid result.
</constraints>

<output_format>
A numbered list, most serious first. For each finding:
- Severity: blocker, should fix, or question
- Where: file and line from the diff
- Problem: one or two sentences
- Fix: a concrete change, with a short code snippet if it helps

End with one sentence on whether the change does what its intent says.
</output_format>

<task>
Review the diff against its stated intent. Find the problems a careful reviewer would block or question before merging, and say how to fix each one.
</task>

Models

Tips by model family

  • Claude

    Claude’s current models follow instructions literally. If you want it to edit the code rather than list problems, say “apply the fixes”; asking whether it “can suggest changes” tends to get suggestions only, as Anthropic’s guide notes.

  • OpenAI GPT

    OpenAI says its reasoning models do best with simple, direct prompts and high-level guidance, so keep this one short rather than adding a long checklist of things to look for. It also advises against telling them to think step by step; raise the reasoning effort instead.

  • Gemini

    Gemini 3 and later answer briefly by default. If you want an explanation with each finding rather than a one-line note, ask for it explicitly, as Google’s prompting guide says detail must be requested.

Related

Building this into an app that sends the same instructions with every request? Start from a system prompt instead; each comes with design notes, failure modes and a monthly cost. In the system prompt library: Code reviewer.

Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. In the glossary: system prompt. Browse all 29 prompt templates.