System prompt · Coding
Code review system prompt that finds real problems
Use this to review pull requests in CI or on demand. The usual problem with AI code review isn’t that it misses things; it’s noise. Twenty comments about naming bury the one real bug, and developers learn to ignore the bot. This prompt ranks findings by severity, requires each one to quote the line it’s about and say what goes wrong, and tells the reviewer that “no issues found” is a good answer. Style comments are allowed only when they hide a real risk.
Prompt
The system prompt
359 tokens with OpenAI o200k_base (gpt-tokenizer 4.0.0), placeholders unfilled. Original writing, free to copy and adapt.
You review code changes for {{team}}. Your reviews are read by busy engineers, so every comment must be worth their time. A review with no findings is a good outcome, not a failure.
<what_to_look_for>
In order of importance:
1. Correctness: logic errors, unhandled cases, race conditions, wrong assumptions about inputs.
2. Security: injection, broken authorisation, unsafe deserialisation, secrets in code, missing input validation.
3. Data and reliability: data loss, migrations that can't roll back, missing error handling on I/O.
4. Maintainability: only when it will clearly cause bugs later, such as duplicated logic that must stay in sync.
Ignore formatting, naming preferences and anything a linter would catch.
</what_to_look_for>
<rules>
- Review only the changed lines and the code they directly affect.
- For each finding, quote the exact line or lines, explain what goes wrong and when, and suggest a fix.
- If you're not sure something is a bug because you can't see related code, say what you'd need to check instead of asserting it.
- Don't repeat a finding for every occurrence; list the locations once.
- Project rules: {{project_rules}}
</rules>
<output_format>
Return Markdown in exactly this shape:
## Summary
One or two sentences: what the change does and whether it is safe to merge.
## Findings
For each finding, most severe first:
### [severity] Short title
- **Where:** file:line
- **Problem:** what goes wrong and when
- **Fix:** the change to make
Severity is one of: blocker, major, minor. If there are no findings, write "No issues found." under Findings.
</output_format>Variables
What to fill in
Fill these once per deployment. Anything that changes per request, such as the user’s name or today’s date, belongs in the user message so the system prompt stays identical and cacheable.
- {{team}}
- The team or repository.
- e.g. the payments API team
- {{project_rules}}
- Repository rules a reviewer should enforce.
- e.g. All money amounts are integers in minor units. Every endpoint checks the caller owns the account.
Design notes
Why each part is there
Role line and “no findings is good”
Sets the audience and makes silence acceptable. Without it, models tend to produce some finding for every diff, which is where the noise comes from. Anthropic advises giving the reason behind an instruction, here that engineers are busy.
Follows: Anthropic: Prompting best practices
<what_to_look_for>
An ordered list tells the model how to prioritise, and the last line removes the categories a linter already covers. Google’s guide recommends stating constraints explicitly; listing what to ignore is a constraint.
Follows: Google: Prompt design strategies · Anthropic: Prompting best practices
<rules>
Quoting the line grounds each finding in the actual code, the same idea as Anthropic’s advice to ground answers in quotes. Allowing “I’d need to check X” replaces confident false positives with honest uncertainty.
Follows: Anthropic: Reduce hallucinations
<output_format>
A fixed Markdown shape so your CI bot can post it as-is or parse severities. OpenAI and Anthropic both recommend specifying the exact output format; showing the skeleton is more reliable than describing it.
Follows: OpenAI: Prompt engineering · Anthropic: Prompting best practices
Try it
A message to test it with
```diff
--- a/src/accounts.ts
+++ b/src/accounts.ts
@@ -10,6 +10,10 @@
+export async function getStatement(req: Request) {
+ const id = new URL(req.url).searchParams.get("account");
+ const rows = await db.query(`SELECT * FROM statements WHERE account_id = ${id}`);
+ return Response.json(rows);
+}
```Adapt
How to adapt it
- Fill
{{project_rules}}with invariants a reviewer must check, such as authorisation on every endpoint or money stored as integers. These are where the model adds most value. - To post inline comments, switch the output to JSON with
file,line,severity,problemandfix, and use your provider’s structured output feature. - For security-only reviews, cut the list to items 1 and 2 and raise the bar for “minor”.
- Send the full file around each hunk, not just the diff, when the change depends on surrounding code.
Failure modes
Common failure modes
- Many minor findings, few real ones.
- Drop “minor” from the severity list, or tell it to report at most three minor findings.
- False positives about code outside the diff.
- Send more context, or rely on the “say what you’d need to check” rule and filter those comments out of auto-posting.
- Inconsistent output that breaks the CI parser.
- Use structured outputs with a JSON schema instead of Markdown when a program reads the review.
Cost
What it costs to send with every request
| Model | Without caching | With caching |
|---|---|---|
| Claude Sonnet 5.5estimate: this model’s tokenizer isn’t public, so its count may differ | $218.39 | Not cached: under the 512-token minimum |
| Claude Haiku 5.5estimate: this model’s tokenizer isn’t public, so its count may differ | $10.92 | Not cached: under the 512-token minimum |
| GPT-6.1 Solo200k_base count; OpenAI hasn’t published this model’s tokenizer | $218.39 | Not cached: under the 1,024-token minimum |
| Gemini 3.8 Flashestimate: this model’s tokenizer isn’t public, so its count may differ | $81.90 | Not cached: under the 4,096-token minimum |
A prompt under a provider’s minimum is still billed in full on every call. Tool definitions sit before the system prompt in the cached prefix, so together they may cross it. Price it at your own traffic.
Placement
Where it goes in each API
The prompt is fixed per repository; it is cached once your project rules take it past the provider’s minimum (512 tokens on Claude 5.5 models, 1,024 on OpenAI). Put the diff and any file context in the user turn, wrapped in clear delimiters such as a fenced block or <diff> tags. When the diff is large, put it first and the request last; Anthropic reports that queries at the end can improve quality by up to 30 percent with long inputs.
| API | Where the system prompt goes | Worth knowing |
|---|---|---|
| OpenAI Responses API | instructions | Applies to that request only: with previous_response_id, send it again every turn. |
| OpenAI Chat Completions | a developer message first in messages | Replaces the system role for o1 and newer models; developer messages take priority over user messages. |
| Anthropic Messages API | top-level system | No system role inside messages. Pass it as a text block with cache_control to cache it. |
| Gemini generateContent | systemInstruction | Text only. Still supported; Google recommends the Interactions API for new work. |
| Gemini Interactions API | top-level system_instruction | Sent beside model and input. Applies to that interaction only: with previous_interaction_id, send it again every turn. |
Related
Related system prompts and tools
- Coding assistant for TypeScript and ReactCoding
- Unit test writerCoding
- Pull request description writerCoding
Need it once, for a single task or in a chat window? A prompt template is one message with {{variables}} you fill each time: Code review prompt template or Security code review prompt template.
Prompt diffChoosing a model for coding agentsBatch API calculatorAll system prompts