TL;DR: Here are 35 AI prompts for code review, debugging, and refactoring, organized into three targeted passes: review (security, performance, readability), debugging (error analysis, root cause), and behavior-preserving refactoring. The key insight most prompt lists skip is that running separate passes on the same code catches more issues than one combined review. Every prompt uses [bracketed variables] you fill in with your stack details.
What are the best AI prompts for code review in 2026?
The best AI prompts for code review are targeted by dimension, not general requests for "all feedback." Asking an AI to "review this code" produces surface-level observations across every category at once. Asking it to "review this code specifically for authentication and authorization gaps, citing every finding with a line number and severity" produces depth that is actually useful in a PR. AI prompts for code review work best when you treat the model as a specialized reviewer you brief with a focused scope, not a generalist scanning everything simultaneously.
This guide gives you 35 prompts organized across three passes: review (security, performance, readability), debugging (error analysis, root cause tracing), and refactoring (behavior-preserving rewrites). Our guide on writing better ChatGPT prompts explains the underlying structure; 25 ChatGPT Prompts for Developers covers the broader developer workflow including code generation and architecture planning. This post is the reference you reach for when you are reviewing or debugging code that already exists. For saving and reusing these prompts with your stack details pre-filled, see how reusable prompt variables reduce the setup time per review to under a minute.
What prompt structure works for code review and debugging?
Every prompt in this guide follows what we call the five-component code prompt system: role, context, task, constraints, and output format. Remove any one component and the model fills the gap with assumptions that rarely match your actual stack or review goal.
| Component | What to include | Why it matters |
|---|---|---|
| Role | "Act as a senior [language] security engineer" | Anchors the model's review lens and vocabulary |
| Context | Language, framework, version, code purpose | Without this, review is abstract and generic |
| Task | Specific review type: security, performance, refactor | Scopes feedback to the dimension that matters |
| Constraints | "Flag with line numbers; rank by severity" | Makes output immediately actionable |
| Output format | Numbered list, table, or structured report | Controls how feedback is delivered |
The same five components apply whether you are asking for a security review, a root cause analysis, or a refactoring plan. The difference is only what you put in the task and constraints fields. If you use these prompts repeatedly, saving them to a prompt library with your stack variables pre-filled cuts the setup time from two minutes to ten seconds per review.
How do I use AI for security-focused code review?
A security pass finds a different class of bugs than a performance pass. Run them separately on the same code. These eight prompts cover the most common security review scopes, from general audits through specific vulnerability categories.
1. General security audit
Use when you're reviewing your own code before it handles anything sensitive.
Role: Application security reviewer. You review code you have permission to
review, and you rate a finding by what an attacker actually gains.
Context
- Code: [paste it]
- Language/framework: [and version]
- What it handles: [user input, auth, payments, PII, file uploads]
- Trust boundary: [what is attacker-controlled vs internal]
- Deployment: [public internet, internal network, local]
Task
Review for security issues.
Rules
- Trace attacker-controlled data from entry to sink. Injection, deserialization,
path traversal and SSRF all live on that path.
- Check authorization separately from authentication. "Logged in" is not
"allowed to touch this record", and that gap is the most common real bug.
- Every finding needs the attack, what it gets them, and the fix. Drop anything
you can't tie to a consequence in this code.
- Do not invent CVE numbers, advisory IDs or version-specific claims about
dependencies — say what to check instead.
- Say when the code looks sound. Padding the list wastes the reviewer's trust.
Example of the standard I want
Weak: "This code may be vulnerable to injection attacks."
Strong: "Line 34: req.query.sort is interpolated into ORDER BY. ?sort=id;DROP
dumps the table. Whitelist column names against a fixed array."
Output
Findings ranked by severity with attack path and fix · what you could not
assess from this code alone.
Run this as your first security pass on any new feature branch. The severity sort tells you what to fix before the next deploy versus what can wait for the next sprint.
2. Input validation check
Use when you want to know whether untrusted input is actually being checked.
Role: Engineer who has debugged production incidents caused by input nobody
thought to validate.
Context
- Code: [paste the handler or function]
- Language/framework: [and validation library, if any]
- Input source: [request body, query, headers, file, third-party webhook]
- Expected shape: [types, ranges, formats, required fields]
- Downstream use: [database, shell, filesystem, template, another API]
Task
Review input validation.
Rules
- Validate at the trust boundary, not deep in the call stack. Note anywhere
unvalidated data travels before it's checked.
- Check the boundaries specifically: empty, null, missing key, wrong type,
negative, zero, huge values, unicode, and arrays where a scalar is expected.
- Distinguish validation from sanitization. Rejecting bad input and neutering
it are different decisions with different failure modes.
- Check the error path leaks nothing — a validation message that echoes the
input or names internals is its own problem.
- Watch for mass assignment where a whole object is trusted.
Example of the standard I want
Weak: "Add input validation."
Strong: "limit comes straight from the query string into LIMIT. ?limit=-1 and
?limit=99999999 both reach the DB. Parse to int, clamp to 1-100."
Output
Unvalidated paths with the input that breaks each · missing boundary cases ·
validation to add and where · error-path leaks.
The table format is deliberate here. It produces a checklist you can assign directly in your issue tracker rather than a paragraph the team has to parse.
3. Authentication and authorization gap analysis
Use when you want to check that being logged in isn't being mistaken for being allowed.
Role: Security reviewer focused on access control, the category that static
scanners miss most reliably.
Context
- Code: [paste routes, middleware, handlers]
- Auth mechanism: [session, JWT, OAuth — and where identity comes from]
- Roles and permissions: [the model]
- Resource ownership: [how a record is tied to a user]
- Sensitive operations: [what must never be done by the wrong person]
Task
Find authentication and authorization gaps.
Rules
- For every endpoint, ask both questions separately: is the caller
authenticated, and is this caller allowed to touch this specific object.
- Hunt for IDOR: any handler taking an ID from the request and fetching it
without scoping to the authenticated user.
- Check authorization runs server-side on every request. Client-side checks
and hidden UI are not access control.
- Look for the gaps around the edges: unauthenticated routes next to protected
ones, admin checks by string comparison, tokens that never expire, missing
checks on the update and delete paths where they exist on read.
- Note where you can't see the middleware and are assuming.
Example of the standard I want
Weak: "Ensure proper authorization."
Strong: "GET /invoices/:id authenticates but never checks invoice.userId ===
session.userId. Any logged-in user reads any invoice by ID."
Output
Endpoint table: authenticated, authorized, ownership-scoped · IDOR risks with
the request that exploits each · fixes · what you had to assume.
The "minimum change" constraint is important: without it, the model tends to propose replacing your entire auth layer rather than addressing the specific gaps.
4. SQL and NoSQL injection risk scan
Use when queries are built anywhere near user input.
Role: Reviewer auditing query construction across SQL and NoSQL.
Context
- Code: [paste query-building code]
- Database and driver/ORM: [and version]
- User input reaching queries: [which fields]
- Query types: [reads, writes, aggregations, search]
Task
Scan for injection risk.
Rules
- Parameterized values are safe; identifiers are not. Table names, column names
and ORDER BY direction can't be parameterized — those need a whitelist, and
they're where injection survives in otherwise-safe codebases.
- For NoSQL, check for operator injection: a JSON body supplying {"$ne": null}
where a string was expected bypasses auth checks entirely.
- Check ORM escape hatches — raw(), literal(), whereRaw(), $queryRawUnsafe.
Being on an ORM is not by itself a defence.
- Verify string concatenation and template literals aren't building fragments.
- For each finding, give the exact input that exploits it.
Example of the standard I want
Weak: "Use parameterized queries."
Strong: "Values are parameterized, but ORDER BY ${req.query.sort} is
concatenated. Injectable despite the ORM. Whitelist sortable columns."
Output
Injection points with exploiting input · identifier vs value issues ·
ORM escape hatches used · fixes.
5. API key and secrets exposure check
Use when before committing, or when auditing what's already in the repo.
Role: Reviewer checking for credentials where they don't belong.
Context
- Code/config: [paste it]
- Repo visibility: [public, private, internal]
- Deployment: [how secrets are meant to be supplied]
- Client vs server: [which of this ships to a browser or app bundle]
Task
Check for exposed secrets.
Rules
- Look for: hardcoded keys and tokens, credentials in connection strings,
private keys, secrets in comments or example config, and anything in a
client-visible bundle.
- Framework prefixes matter — anything prefixed for client exposure
(NEXT_PUBLIC_, VITE_, REACT_APP_) is public by definition. Flag any that
holds something sensitive.
- Check what's logged. Secrets in error messages, request logs and stack traces
leak to wherever logs go.
- Note that git history keeps a secret after it's deleted from HEAD — a removal
commit is not remediation.
- Do not print any secret you find. Reference it by location and type.
Example of the standard I want
Weak: "Don't hardcode secrets."
Strong: "config.ts L12: NEXT_PUBLIC_STRIPE_SECRET is a server key on a client
prefix — it ships in the JS bundle. Rotate it, then move it to a
server-only variable."
Output
Findings by location and type, never the value · client-exposure risks ·
logging leaks · remediation including rotation and history.
This prompt is worth running on every file that touches configuration, environment setup, or third-party integrations.
6. Dependency vulnerability flag
Use when you want a read on dependency risk without inventing advisory data.
Role: Engineer assessing dependency risk. You are explicit about what you
cannot know from a manifest alone.
Context
- Manifest: [paste package.json, requirements.txt, go.mod, Gemfile]
- Lockfile present: [yes/no — this changes what's knowable]
- Scanner output: [paste npm audit / Dependabot / Snyk if you have it]
- Runtime exposure: [what's internet-facing]
Task
Assess the dependency surface.
Rules
- Do not state that a specific version has a specific CVE from memory.
Advisory data changes constantly and a confidently wrong CVE is worse than
none. Where scanner output was supplied, work from it; otherwise mark every
version claim [VERIFY WITH SCANNER].
- What you can assess without a scanner: unpinned or wildcard ranges, packages
that look unmaintained or abandoned, duplicated functionality, and
dependencies pulled in for one trivial function.
- Flag anything with install scripts or unusually deep transitive trees.
- Prioritise by exposure — a vulnerability in a build-time tool is not the same
risk as one in a request path.
- Recommend the scanner commands to run.
Example of the standard I want
Weak: "lodash 4.17.15 has a prototype pollution vulnerability (CVE-2020-8203)."
Strong: "lodash is pinned to 4.17.15 and is used in a request path — run
`npm audit --production` and check advisories [VERIFY WITH SCANNER].
Only two helpers are used; both are now native."
Output
What's assessable from the manifest · what needs a scanner, with commands ·
risk ranked by runtime exposure · removable dependencies.
7. OWASP Top 10 coverage check
Use when you want structured coverage rather than whatever the reviewer happens to notice.
Role: Security reviewer working a checklist so coverage doesn't depend on
what catches your eye.
Context
- Code: [paste it, or describe the application if reviewing at design level]
- Application type: [web app, API, CLI, mobile backend]
- Stack: [framework and version]
- What's in scope: [the parts you can actually see]
Task
Walk the OWASP Top 10 categories against this code.
Rules
- Address every category explicitly, including the ones that don't apply —
"not applicable, no file uploads here" is a useful result and stops silent
gaps.
- For each applicable category, either cite the specific code that's at risk or
state clearly that you found nothing.
- Be honest about scope. Several categories (logging and monitoring,
configuration, supply chain) can't be judged from application code alone —
list those as unassessed rather than passed.
- Rank findings by exploitability in this deployment, not by the category's
general severity.
Example of the standard I want
Weak: "A03 Injection: Passed."
Strong: "A01 Broken Access Control: FOUND — three handlers fetch by ID without
ownership scoping (L44, L61, L79). A09 Logging: NOT ASSESSABLE from
application code; needs infrastructure review."
Output
Category-by-category: found / clean / not applicable / not assessable, with
evidence · findings ranked by exploitability · what needs review beyond this code.
8. Rate limiting and denial-of-service surface
Use when an endpoint does real work and anyone on the internet can call it.
Role: Engineer assessing abuse and denial-of-service surface, including the
expensive-operation kind rather than only raw traffic floods.
Context
- Code: [paste endpoints and any existing limiting]
- Deployment: [and what sits in front — CDN, WAF, load balancer]
- Expensive operations: [what costs CPU, memory, money or third-party quota]
- Auth: [which endpoints are reachable unauthenticated]
Task
Review the rate limiting and DoS surface.
Rules
- Find unauthenticated endpoints that trigger expensive work: report
generation, file processing, email sending, third-party API calls, anything
billable. These are the real risk, not request volume.
- Check for unbounded input: pagination with no maximum, uploads with no size
cap, regexes over user input that can backtrack, recursive or nested payloads.
- Assess what limiting exists — per-IP alone is weak behind NAT or a proxy,
and in-memory counters don't hold across instances.
- Note where limiting belongs at the edge rather than in application code.
- Include the account-lockout angle: a login limiter can be turned into a
denial of service against a real user.
Example of the standard I want
Weak: "Add rate limiting to the API."
Strong: "POST /export is unauthenticated and builds a PDF from an unbounded
date range. One client can pin every worker. Cap the range, require
auth, queue the job."
Output
Expensive unauthenticated paths · unbounded inputs · gaps in current limiting ·
what belongs at the edge vs in code · lockout risks.
How do I catch performance problems with AI prompts?
Performance review prompts produce better results when you ask the model to rank bottlenecks by impact and explain the algorithmic complexity tradeoff. "What's slow?" produces a list; "rank these bottlenecks by likely impact on [your expected load]" produces a prioritized action plan.
9. General performance bottleneck scan
Use when something is slow and you want candidates before you start profiling.
Role: Performance engineer. You are disciplined about the difference between
a hypothesis and a measurement.
Context
- Code: [paste it]
- Observed symptom: [what's slow, and how slow — with numbers if you have them]
- Profiler output: [paste it, or "none yet"]
- Scale: [request volume, data size, concurrency]
- Environment: [where it runs, and where it's fine]
Task
Identify likely bottlenecks.
Rules
- If there's no profiler output, say plainly that everything below is a
hypothesis to test, and give the cheapest way to measure each one.
- Look for the usual causes in order of frequency: queries in loops,
synchronous I/O on a hot path, unnecessary serialization, unbounded
in-memory collections, and recomputation of stable values.
- Estimate the ceiling on each fix. If a suspect path is 5% of runtime,
optimising it perfectly buys 5% — say so before anyone spends a week on it.
- Do not recommend micro-optimisations ahead of algorithmic or I/O problems.
Example of the standard I want
Weak: "The loop is inefficient — optimize it."
Strong: "L40 queries inside a loop over results: 1 + N round trips. At 500 rows
that's ~500 queries. Batch it. Unmeasured — confirm with query logs."
Output
Ranked candidates with reasoning and expected gain · measured vs hypothesised,
labelled · the one measurement to take first.
10. Database query performance review
Use when the database is the suspect and you have the queries to look at.
Role: Database performance engineer. You read plans before rewriting SQL.
Context
- Queries: [paste them, or the ORM code that generates them]
- Engine and version: [Postgres, MySQL, MongoDB]
- EXPLAIN output: [paste it, or "none"]
- Table sizes and indexes: [row counts and what exists]
- Access pattern: [read-heavy, write-heavy, mixed]
Task
Review query performance.
Rules
- Work from the EXPLAIN output. Without it, say what you'd need to see and mark
your reading as a hypothesis.
- Name the specific problem — sequential scan, bad join order, non-sargable
predicate, sort spilling to disk, N+1 — before proposing a fix.
- Any index you suggest carries a write cost and disk footprint. State them.
Suggesting indexes without cost is how write throughput quietly dies.
- Check whether a rewrite changes semantics around NULLs, duplicates or
ordering. If it does, flag it.
- Watch for SELECT * on wide tables and for pagination with large OFFSET.
Example of the standard I want
Weak: "Add an index on created_at."
Strong: "Seq scan on orders (2.1M rows): WHERE DATE(created_at) = ... isn't
sargable. Compare against a range instead and the existing index is
used — no new index needed."
Output
Per query: problem, fix, expected effect · indexes with their write cost ·
semantic changes · what to measure after.
Providing table size context changes the model's recommendations significantly. A missing index on a 10,000-row table is a low-priority finding; the same missing index on a 10-million-row table is critical.
11. Memory usage and leak detection
Use when memory grows and doesn't come back down.
Role: Engineer diagnosing memory growth. You separate a leak from legitimate
caching and from ordinary GC behaviour.
Context
- Code: [paste it]
- Runtime: [language, version, GC if relevant]
- Symptom: [growth rate, over what period, whether it plateaus]
- Heap snapshots or metrics: [paste them, or "none"]
- Restart behaviour: [does restarting reset it]
Task
Find the likely memory problem.
Rules
- First decide whether this is a leak at all. Growth that plateaus may be a
cache or a pool working as designed — calling that a leak sends people
chasing nothing.
- Look for the usual retainers: listeners added without removal, unbounded
caches or maps keyed by request data, closures capturing large scopes,
timers never cleared, and global accumulators.
- Check for unbounded buffering: reading a whole file or result set into memory
where streaming was intended.
- Without snapshots, say what to capture and when — two snapshots under load
and a diff beats any amount of code reading.
- Note where a fix trades memory for latency.
Example of the standard I want
Weak: "There may be a memory leak in the event handler."
Strong: "subscribe() on every request with no unsubscribe on the response path.
Each request retains the handler and its closure — grows linearly
with traffic, never plateaus."
Output
Leak vs expected growth, with reasoning · suspected retainers with evidence ·
what to capture to confirm · fixes and their trade-offs.
Memory issues are among the hardest to reproduce in development because they accumulate slowly and only become visible under sustained production load. Running this prompt before a feature ships surfaces patterns the model can recognize structurally — event listeners added inside loops, closures capturing large objects — that would not show up in unit tests.
12. Algorithm complexity review
Use when the code is slow in a way that gets worse as data grows.
Role: Engineer reviewing algorithmic complexity, with attention to the input
sizes that actually occur.
Context
- Code: [paste it]
- Input sizes: [typical and worst case — this decides whether complexity matters]
- Growth expectation: [how the data will scale]
- Current performance: [if measured]
Task
Review time and space complexity.
Rules
- State complexity for each significant operation, and name the input it's in
terms of. "O(n²)" is meaningless without saying what n is.
- Judge against the actual input size. O(n²) on 20 items is fine and rewriting
it is wasted effort; say so rather than flagging it reflexively.
- Look for hidden costs: an `in` check on a list, string concatenation in a
loop, sorting inside a loop, repeated linear scans that could be a hash lookup.
- Include space complexity where it matters.
- For each improvement, give the complexity change and the readability cost.
Example of the standard I want
Weak: "This nested loop is O(n²)."
Strong: "O(n·m): for each of n orders it scans all m products. At n=500,
m=10,000 that's 5M comparisons. Index products by id first — O(n+m),
same readability."
Output
Complexity per operation with the relevant input · which matter at your sizes ·
which don't and can be left · improvements with trade-offs.
The "show before and after complexity" instruction is what converts this from an analysis into an actionable change. Without it, the model often describes the problem in general terms without committing to a specific alternative, leaving you to infer what "use a hash map instead" actually means in context.
13. Async and concurrency review
Use when concurrent code behaves differently under load than it does in tests.
Role: Engineer reviewing concurrent code. You assume anything that can
interleave will, eventually, in production.
Context
- Code: [paste it]
- Runtime model: [single-threaded event loop, threads, goroutines, workers]
- Shared state: [what more than one path touches]
- Symptom: [if there is one — intermittent failures, wrong totals, hangs]
- Deployment: [single instance or many]
Task
Review for concurrency problems.
Rules
- Find check-then-act sequences on shared state. Read-modify-write without
atomicity is the most common race and it survives every local test.
- Check await points specifically: state read before an await may be stale
after it.
- Look for unhandled promise rejections, missing awaits, and fire-and-forget
calls whose failures vanish.
- Distinguish problems that need real parallelism from those that occur on a
single-threaded event loop too — both are real, and the second surprises
people.
- Check whether locks or transactions actually cover the whole invariant, and
whether a lock is in-process where the app runs multiple instances.
Example of the standard I want
Weak: "There might be a race condition here."
Strong: "L22 reads balance, awaits the gateway, then writes balance - amount.
Two concurrent requests both read the old value; one write is lost.
Needs an atomic decrement or a transaction with a row lock."
Output
Races with the interleaving that triggers each · await-point staleness ·
swallowed failures · fixes, noting which need to work across instances.
Specify the async model explicitly. What counts as a race condition in a goroutine-based system differs from what counts as one in an async/await Promise chain. Without this context, the model applies generic concurrency advice that may not map to your runtime.
14. Caching opportunity analysis
Use when you're considering adding a cache and want to know if it's the right move.
Role: Engineer who treats a cache as a correctness liability to be justified,
not a default performance fix.
Context
- Code: [paste it]
- What's slow: [the measured operation]
- Data volatility: [how often the underlying data changes]
- Correctness tolerance: [can a user see stale data, and for how long]
- Infrastructure: [single instance, multi-instance, existing cache layer]
Task
Identify caching opportunities.
Rules
- First check whether the underlying operation should just be faster. Caching a
bad query hides it and doubles the surface area.
- For each candidate, state: what's cached, the key, the TTL, and precisely
what happens when the source changes. Invalidation is the hard part and
vagueness there is where bugs come from.
- Never cache anything user-specific under a shared key. Cross-user leakage
through a cache is a security bug, not a performance bug.
- Check the multi-instance case — in-process caches diverge between instances.
- Estimate hit rate. A cache below a useful hit rate adds latency and complexity
for nothing.
Example of the standard I want
Weak: "Cache the user data to improve performance."
Strong: "Cache the product catalogue (changes ~daily, identical for all users):
key products:v1:{categoryId}, TTL 1h, busted on the admin write path.
Do NOT cache the cart — per-user and changes constantly."
Output
Candidates with key, TTL and invalidation · what not to cache and why ·
multi-instance considerations · expected hit rate · what to fix instead of caching.
Include whether you currently have a cache layer in the stack field. If you do, the model suggests cache keys and TTL values calibrated to your existing infrastructure. If you do not, it suggests which layer to add first and what it would unblock.
How do I use AI to review for readability and maintainability?
Readability prompts catch the problems that accumulate into technical debt. They are most useful before a code review cycle, giving the author a chance to clean up before peers read the code. The key is specifying your team's conventions in the prompt so the model reviews against your actual standards, not general best practices.
15. General readability review
Use when you want a readability review that isn't just someone's formatting preferences.
Role: Senior engineer reviewing for the next person who has to change this.
You are silent about taste and direct about genuine confusion.
Context
- Code: [paste it]
- Language: [and version]
- Team conventions: [paste the style guide, or "infer from the code"]
- Who maintains it: [experience level, familiarity with this area]
- How often it changes: [rarely-touched code has a different bar]
Task
Review for readability.
Rules
- Only flag what a competent reader would genuinely misread or have to re-read.
Formatting a linter handles is not a review comment.
- Look for: names that lie, functions doing several unrelated things, deep
nesting, boolean parameters at call sites, and magic values with no name.
- Comments explaining what the code does are usually a naming problem; comments
explaining why it does it are the valuable ones. Distinguish them.
- Judge against how often the code changes. Rarely-touched working code has a
higher bar for churn.
- Say when it reads well. A review that always finds something is noise.
Example of the standard I want
Weak: "Consider renaming this variable to something clearer."
Strong: "`data` at L12 holds validated user records; `data` at L40 holds raw
API rows. Same name, different shapes, 30 lines apart — reads as a
bug on first pass."
Output
Findings with location and the specific confusion each causes · what already
reads well · what to leave alone.
Including your team's style conventions in the prompt is what separates a useful readability review from generic feedback. Without them, the model reviews against the average of the internet's style preferences, which may contradict your team's deliberate choices.
16. Function complexity and single-responsibility check
Use when a function has grown and you're deciding whether to split it.
Role: Engineer who splits functions when it helps a reader, not to hit a line
count.
Context
- Code: [paste the function]
- What it's meant to do: [in one sentence]
- Callers: [how many, and how they use it]
- Test coverage: [what exists — this changes how safe a split is]
Task
Assess complexity and single responsibility.
Rules
- Try to state the function's job in one sentence without "and". If you can't,
that's the finding, and the conjunctions show the seams.
- Report cyclomatic complexity and where the branching concentrates.
- Count the levels of abstraction it mixes. A function doing HTTP handling,
business rules and SQL in one body is harder to follow than a long one that
stays at one level.
- Only propose a split you can name well. "Extract helper1" makes things worse.
- Note where extraction would need a lot of parameters passed through — that's
a sign the seam is in the wrong place.
Example of the standard I want
Weak: "This function is too long — break it up."
Strong: "Three jobs: parses the webhook, decides entitlement, writes the audit
row. The entitlement rules (L30-64) are the part with tests and the
part that changes — extract that first."
Output
One-sentence job attempt · complexity and where it sits · abstraction levels
mixed · proposed splits with names and order · what to leave.
The instruction to name the proposed sub-functions is the part most developers skip when writing this prompt themselves. Without it, you get a recommendation to "extract this logic into a separate function" with no suggestion of what to call it — which puts the naming work back on you.
17. Naming review
Use when you keep having to read the implementation to know what something holds.
Role: Engineer reviewing names, aware that renaming is cheap now and expensive
once something is public.
Context
- Code: [paste it]
- Domain: [the business language this lives in]
- Conventions: [casing, prefixes, existing vocabulary in the codebase]
- Public surface: [what's exported or used externally]
Task
Review naming.
Rules
- Flag names that are wrong or misleading before names that are merely short.
`userList` holding a Map is worse than `u`.
- Check the codebase's own vocabulary is used consistently. If the domain says
"subscriber", one file saying "member" costs every future reader a translation.
- Booleans should read as predicates (isActive, hasAccess). Functions should
say what they return or what they change.
- Note where a name has drifted from what the thing now does — that's the most
common real naming bug.
- Mark renames on the public surface as breaking, and say what else moves.
Example of the standard I want
Weak: "Rename `d` to something more descriptive."
Strong: "`checkUser()` doesn't check anything — it creates a session as a side
effect. Name says query, behaviour is a write. `startSession()`."
Output
Misleading names first, then unclear ones · vocabulary inconsistencies ·
suggested names with reasoning · which renames are breaking changes.
The "do not flag conventional names" instruction prevents the model from suggesting that you rename loop variables and other standard idioms. Without this constraint, naming reviews often produce noise that drowns out the genuinely ambiguous names worth fixing.
18. Documentation and comment quality review
Use when you're deciding what actually needs documenting before a handover.
Role: Engineer who thinks most comments are noise and the missing ones are
expensive.
Context
- Code: [paste it]
- Audience: [team members, external consumers, future you]
- Public API: [what others call]
- Non-obvious decisions: [anything with history behind it]
Task
Review documentation and comments.
Rules
- Find comments that restate the code and add nothing — they rot and then
actively mislead.
- Find the missing why. Workarounds, ordering requirements, deliberate
deviations from the obvious approach: undocumented, these get "cleaned up"
by the next person and the bug returns.
- Check comments still match the code. A stale comment is worse than none.
- For public API, check parameters, return shape, thrown errors and side effects
are documented.
- Don't ask for docstrings on self-evident functions.
Example of the standard I want
Weak: "Add a comment explaining this function."
Strong: "L88 retries 3 times with no explanation. Whether that's the gateway's
documented behaviour or a guess matters to whoever tunes it — that's
the comment worth adding. Delete `// increment i` on L91."
Output
Comments to delete · missing why-comments with what each should say · stale
comments · public API documentation gaps.
Asking the model to provide the corrected version, not just flag the problem, makes this prompt immediately actionable. You can accept, modify, or reject each suggestion rather than rewriting documentation from scratch.
19. DRY principles and duplication check
Use when you're weighing whether repeated code is worth unifying.
Role: Engineer who knows the wrong abstraction costs more than duplication.
Context
- Code: [paste the repeated sections]
- How many places: [and whether they change together]
- Change history: [have they diverged over time?]
- Domain: [do they represent the same concept or just look alike?]
Task
Review duplication.
Rules
- Distinguish true duplication — same knowledge, must change together — from
coincidental similarity. Code that merely looks alike will diverge, and
unifying it creates a function with a boolean parameter and two behaviours.
- Use the change history. If copies have already diverged, that is evidence
they are different concepts.
- For genuine duplication, name what the shared concept actually is. If you
can't name it, don't extract it yet.
- Weigh the coupling cost: extraction ties these call sites together for good.
- Say explicitly where duplication should stay.
Example of the standard I want
Weak: "This logic is duplicated in three places — extract it."
Strong: "Two of the three are the same rule (VAT calculation, must stay in
sync). The third looks identical but is a shipping surcharge that
happens to use the same rate today. Unify the first two only."
Output
True duplication with the shared concept named · coincidental similarity to
leave alone · proposed extraction with its coupling cost · order.
Paste multiple files when you suspect cross-file duplication. The model can identify the same transformation appearing in different modules only if it can see all the modules simultaneously. Single-file review misses the most common form of duplication in larger codebases.
20. Error handling completeness review
Use when you want to know what happens on the paths nobody tested.
Role: Engineer who has been paged at 3am by a swallowed exception.
Context
- Code: [paste it]
- Language conventions: [exceptions, Result types, error-first callbacks]
- Failure modes: [what can realistically go wrong — network, disk, upstream]
- Where it runs: [request path, background job, startup]
- Who sees the error: [end user, operator, nobody]
Task
Review error handling completeness.
Rules
- Find swallowed errors — empty catch blocks, catches that only log at debug,
promises without rejection handling. These are the ones that cost hours later.
- Check every external call has a failure path: network, filesystem, database,
third-party API, JSON parsing.
- Distinguish recoverable from unrecoverable. Retrying a 400 is pointless;
swallowing a 500 hides an outage.
- Check errors carry enough context to debug from a log line alone, and that
they don't leak internals to the user.
- Check partial failure: if the operation writes in several places and fails
midway, what state is left behind.
Example of the standard I want
Weak: "Add error handling to this function."
Strong: "L45 catch is empty with `// ignore`. A failed webhook delivery here is
indistinguishable from success — the retry queue never sees it. Log
with the event ID and re-throw."
Output
Swallowed errors by location · unhandled external calls · recoverable vs not ·
context missing from messages · partial-failure states.
The "describe the failure scenario" instruction is what makes this review useful to someone who has never thought about a specific error path. A bare list of uncaught exceptions is easy to dismiss; a description of "this function will crash the entire request handler if the database is unavailable, returning a 500 with the full stack trace" is not.
What AI prompts help debug errors and trace root causes?
Debugging prompts produce better results when you include the full error message, the complete stack trace, and the framework versions. The goal is root cause explanation first, then the minimum fix. Models that explain root causes produce fewer regression patches than models that patch symptoms.
21. Error message analysis
Use when you have an error message and want the cause rather than the symptom.
Role: Engineer debugging from evidence. You say when the evidence is thin
rather than guessing confidently.
Context
- Error message: [paste it verbatim]
- When it happens: [always, intermittently, under load, one environment]
- What the user was doing: [the triggering action]
- Recent changes: [deploys, config, dependency bumps — or "unknown"]
- Relevant code: [paste if available]
Task
Interpret the error and say what to do.
Rules
- Separate what the message proves from what you're inferring. Label the
inference — a confident wrong diagnosis costs more than an honest uncertain one.
- Explain what the error actually means, including any misleading wording.
Several common runtime messages point at a symptom, not the cause.
- Where the message can't distinguish between causes, name the single check
that separates them.
- Don't propose a fix that only silences the error without saying that's what
it does.
Example of the standard I want
Weak: "This means a variable is undefined — add a null check."
Strong: "'Cannot read property id of undefined' at L20 means getUser() returned
undefined, not that user.id is wrong. The null check hides it; find
why the lookup missed — likely the cache path at L12 returning
undefined instead of null."
Output
What the message proves · most likely cause, marked as inference · the check
that confirms it · the real fix vs the silencing fix.
The three-step structure is deliberate. It stops the model from jumping straight to a patch and forces it to articulate the actual cause first.
22. Stack trace interpretation
Use when you have a full stack trace and want the frame that matters.
Role: Engineer who reads traces bottom-up and knows the throwing line is
rarely the broken one.
Context
- Stack trace: [paste the whole thing, including causes]
- Language/runtime: [and version]
- Source: [production, local, CI]
- Code: [paste the frames you have]
- Frequency: [always, intermittent, once]
Task
Interpret the trace.
Rules
- Find the first frame that is our code rather than library internals. That's
usually where the wrong assumption lives, even though the throw is deeper.
- Follow 'caused by' chains to the root. The outermost exception is often a
wrapper that says nothing useful.
- Watch for async traces: the stack may not show the call path that set up the
failure, so say what's missing rather than reading it as complete.
- Note minified or transpiled frames and what you'd need — source maps — to read
them properly.
- Separate proof from inference.
Example of the standard I want
Weak: "The error occurs in the database module at line 200."
Strong: "Throw is in the driver, but the first frame of ours is
orderService.ts:47 passing customerId as undefined. The driver is
reporting our bad input correctly."
Output
Root cause frame and why · the chain summarised · what the trace can't show ·
next step to confirm.
This prompt is especially useful when the error originates in a library you did not write. Walking through the call chain from your entry point to the failure in a third-party module explains which of your assumptions triggered the library's error condition.
23. Root cause with 5-Whys analysis
Use when you've fixed the symptom and want to know why it happened at all.
Role: Incident analyst running a root cause analysis. You keep asking why
past the first satisfying answer, and you stay off blame.
Context
- What happened: [the failure, precisely]
- Immediate cause: [what you already know]
- Timeline: [when it started, when it was noticed, when it was fixed]
- Detection: [how you found out — this is usually its own finding]
- System context: [what else was involved]
Task
Run a 5-Whys analysis.
Rules
- Each why must follow from the previous answer's evidence, not from a
plausible story. Say when you're inferring.
- Stop when you reach something actionable, not at an arbitrary five. Stopping
at "human error" is stopping too early — ask what made the error easy.
- Address detection separately from cause. "Why did it take four hours to
notice" is often the more valuable branch.
- Stay on systems and conditions, not individuals.
- Distinguish the trigger from the underlying condition. The deploy that
exposed a latent bug is not the cause of the bug.
Example of the standard I want
Weak: "Why did it fail? A developer forgot to add validation."
Strong: "Why was it deployable without validation? The schema is defined in
two places and only one is enforced at the boundary — nothing in CI
checks they agree."
Output
The why-chain with evidence at each step · trigger vs underlying condition ·
the detection branch · at most three actions with owners.
This prompt works especially well for bugs that have been patched multiple times without the team finding the real cause. The 5-Whys framing explicitly separates symptom from root cause.
24. Race condition and async bug analysis
Use when the bug only shows up sometimes, and usually not on your machine.
Role: Engineer hunting a nondeterministic bug. You reason about interleavings
rather than re-running and hoping.
Context
- Code: [paste the async or concurrent sections]
- Symptom: [what's wrong, and how often]
- Where: [environment, load level, single or multi instance]
- Runtime model: [event loop, threads, workers]
- What's shared: [state touched by more than one path]
- Logs: [paste anything from a failure]
Task
Find the race.
Rules
- Identify every shared mutable thing and every await or yield point where
another task can interleave.
- Look for read-modify-write without atomicity, check-then-act, and ordering
assumptions between independent async operations.
- Consider startup and shutdown races — initialization not awaited, cleanup
during an in-flight request.
- Describe the exact interleaving that produces the symptom. If you can't
construct one, say so; it may not be a race.
- Prefer fixes that remove the shared state over fixes that add locking.
Example of the standard I want
Weak: "There's likely a race condition in the async code."
Strong: "Request A reads count=5, awaits. Request B reads count=5, awaits,
writes 6. A resumes and writes 6. Two increments, one result — matches
the undercount in the logs."
Output
Shared state and interleaving points · the specific sequence producing the
symptom · how to reproduce deterministically · fix, preferring removed state
over added locks.
The "describe the exact sequence" instruction distinguishes a useful response from a generic warning about concurrency. Knowing "the race occurs when goroutine A reads the map key between goroutine B's delete and goroutine C's write, producing a nil pointer dereference" is actionable. "This code may have race conditions" is not.
25. Regression analysis
Use when something that used to work doesn't, and you need the change that did it.
Role: Engineer narrowing a regression. You work from evidence about what
changed, not from guessing what looks suspicious.
Context
- Broken behaviour: [what's wrong now]
- Working behaviour: [what it used to do]
- Last known good: [version, date or commit]
- Changes since: [commits, deploys, dependency updates, config, data]
- Reproduction: [steps, and how reliably]
Task
Identify the likely cause.
Rules
- Rank the changes by how plausibly each could produce this specific symptom.
A large diff in an unrelated area outranks nothing.
- Include the non-code candidates: dependency updates through a caret range,
config, feature flags, upstream API changes, and data that only recently
started containing an edge case. These are missed most often because the
repo looks untouched.
- Recommend a bisect strategy and say what makes a good test command.
- Say what evidence would eliminate each candidate, so the search narrows.
Example of the standard I want
Weak: "Check the recent commits for the cause."
Strong: "Nothing in the diff touches parsing, but the lockfile moved date-fns
2.29→2.30 and the symptom is a date off by one. Check that first —
it's one command, and it eliminates the largest candidate."
Output
Ranked candidates with reasoning · non-code causes considered · bisect plan
with a test command · what eliminates each candidate.
The "minimal fix without reverting" instruction is important when the change that introduced the regression was itself correct and needed. Reverting is often faster in the short term but throws away the intentional improvement. A minimal fix preserves the intent of the change while correcting the side effect.
26. API contract mismatch debugging
Use when two services disagree about the shape of the data between them.
Role: Engineer debugging an integration boundary, where most bugs are
disagreements about a contract nobody wrote down.
Context
- Expected contract: [schema, docs, or types]
- Actual payload: [paste a real request or response]
- Error: [what fails, and on which side]
- Consumer code: [paste it]
- Recent changes: [either side]
Task
Find the contract mismatch.
Rules
- Compare actual against expected field by field: presence, type, nullability,
casing, date format, number vs string, and nesting depth.
- Watch for the quiet ones: a number arriving as a string, null vs missing key,
an empty array vs absent field, and timezone-naive timestamps. These pass
shallow checks and fail deep in the code.
- Establish which side changed, and whether the contract was ever explicit.
- Check the consumer's assumptions about optional fields — most breakages are
optional fields treated as guaranteed.
- Recommend where to validate so the next mismatch fails loudly at the boundary.
Example of the standard I want
Weak: "The API response doesn't match what the code expects."
Strong: "`total` is a string ('19.99') in the payload, number in our type. It
only surfaces on `total.toFixed()` three layers in. Parse and validate
at the boundary."
Output
Field-level differences · which side changed · assumptions that don't hold ·
boundary validation to add.
Pasting both the expected and actual payloads is the instruction most developers skip, leaving the model to guess which schema is authoritative. With both provided, the model can tell you precisely which field is missing, mistyped, or in the wrong format, and which side of the contract needs to change.
27. Silent failure detection
Use when the system reports success and the work didn't happen.
Role: Engineer hunting failures that don't announce themselves. These are the
expensive ones because nobody knows to look.
Context
- Code: [paste it]
- What should happen: [the expected effect]
- What's observed: [the discrepancy — missing records, unsent emails]
- Logging and monitoring: [what exists]
- Scale: [how often the operation runs]
Task
Find where failures are being swallowed.
Rules
- Look for: empty catch blocks, promises without rejection handling,
fire-and-forget calls, return values that are never checked, and batch loops
that continue past a failed item without recording it.
- Check for conditions that silently do nothing — an early return on a falsy
value, a filter that removes everything, a loop over an empty array.
- Check whether success is actually confirmed or merely assumed. "No exception"
is not the same as "the write landed".
- Distinguish failures that are logged but unmonitored from those never recorded.
Different fixes.
- Recommend the assertion or alert that would have caught this.
Example of the standard I want
Weak: "Errors might not be handled properly."
Strong: "sendEmail() is called without await inside a .map(). A rejection
becomes an unhandled promise rejection the process ignores. The
handler returns 200 whether or not any email sent."
Output
Swallowing points with the failure each hides · assumed vs confirmed success ·
logged-but-unmonitored vs never-recorded · what to assert or alert on.
Silent failures are the hardest bugs to diagnose because they produce no error output. This prompt specifically looks for the patterns that hide them.
28. Variable state tracing
Use when a value is wrong and you need to find where it stopped being right.
Role: Engineer tracing a value through a system, narrowing by bisection rather
than by reading everything.
Context
- Variable/value: [what's wrong]
- Expected vs actual: [both, precisely]
- Code path: [paste the flow]
- Entry point: [where the value starts]
- Known good point: [the last place it was correct, if you know]
Task
Trace where the value goes wrong.
Rules
- Map every point the value is read, written, transformed or passed. Mark where
it's known correct and where it's known wrong — the bug is between those, and
everything outside that range is wasted reading.
- Look for the usual culprits: mutation of a shared object, an implicit type
coercion, an off-by-one, a default overwriting a real value, and destructuring
a field that doesn't exist.
- Include the async dimension — a value can be correct when read and stale by
the time it's used.
- Give the specific log or breakpoint at each candidate, not "add logging".
- Say which single check narrows the range fastest.
Example of the standard I want
Weak: "Add console.log to see where the value changes."
Strong: "Correct at L10, wrong at L60. Bisect at L35 — that's the merge with
`defaults`, and Object.assign there overwrites a provided 0 because
the guard uses `||` rather than `??`."
Output
The value's path with known-good and known-bad points · candidate corruption
points ranked · the exact check at each · the one that bisects fastest.
How do I refactor code with AI without changing existing behavior?
The behavior-preservation constraint is the most important element of any refactoring prompt. Without it, the model treats "improve" as permission to change behavior along with structure. Every refactoring prompt below includes an explicit constraint. Add a test checklist request to any prompt where you want confidence before merging.
29. Behavior-preserving refactor
Use when you need to restructure code without changing what it does.
Role: Engineer refactoring under a strict behaviour-preservation constraint.
Context
- Code: [paste it]
- Why refactor: [what's actually hard about it today]
- Test coverage: [what exists — this decides how safe this is]
- Callers: [who depends on this and whether they can change]
- Constraints: [public API, performance, deadline]
Task
Refactor without changing behaviour.
Rules
- If coverage is thin, say so first and recommend characterisation tests before
touching anything. Refactoring untested code is rewriting it and hoping.
- Preserve observable behaviour exactly, including the ugly parts: error types
and messages, edge-case handling, ordering, and any bug callers may depend on.
If you think a behaviour is a bug, flag it separately rather than fixing it
quietly here.
- Work in small independently-shippable steps, each leaving the code working.
- Note any behaviour change you cannot avoid, however small.
- Don't expand scope into unrelated cleanup.
Example of the standard I want
Weak: "Refactored the function and cleaned up some issues along the way."
Strong: "Extracted validation unchanged. Note: L20 currently returns null for
empty input where the type says string — preserved, but it looks like
a bug. Flagged, not fixed."
Output
Refactored code · the steps in order · behaviour explicitly preserved ·
suspected bugs left alone · what to test first.
30. Extract function refactor
Use when part of a function wants to be its own thing.
Role: Engineer extracting a function, aware that a bad extraction is worse
than a long function.
Context
- Code: [paste the function]
- The part to extract: [or "identify the best candidate"]
- Language conventions: [naming, pure vs side-effecting, module layout]
- Test coverage: [what exists]
Task
Extract the function.
Rules
- The extracted piece needs a name that says what it does without reference to
where it came from. If the best name is `handleStep2`, the seam is wrong.
- Minimise the parameters. If extraction needs six arguments and two out
params, the boundary is in the wrong place — say so instead of extracting.
- Prefer a pure function. If it must have side effects, keep them at one level
and name it so the caller knows.
- Preserve behaviour including early returns and error paths — those often get
lost in extraction.
- Say where it should live: same file, same module, or shared.
Example of the standard I want
Weak: "Extract lines 20-45 into a helper function."
Strong: "L20-45 is entitlement resolution: pure, takes (plan, usage), returns a
boolean. `hasRemainingQuota(plan, usage)`. The surrounding I/O stays."
Output
Extracted function with its name and signature · updated caller · why this
seam · where it belongs · what a test should assert.
Asking the model to show the calling code after extraction is what makes this prompt produce a complete refactor rather than just the extracted function. Without seeing the updated call site, you have to infer how to wire the extraction back in.
31. Design pattern suggestion
Use when the code is getting hard to extend and you're wondering if a pattern helps.
Role: Engineer who reaches for a pattern to solve a demonstrated problem, not
to demonstrate knowledge of patterns.
Context
- Code: [paste it]
- The problem: [what's actually painful — adding cases, testing, duplication]
- Expected changes: [what you know is coming]
- Team familiarity: [with the patterns in question]
- Codebase conventions: [what's already used here]
Task
Assess whether a pattern would help.
Rules
- Start by saying whether a pattern is warranted at all. Often the answer is a
function, a lookup table, or nothing — and recommending that is the more
useful answer.
- Name the specific pain a pattern removes, and be concrete about the cost:
indirection, more files, harder first read.
- Weigh against expected change. A strategy pattern for two cases that will
never grow is pure overhead.
- Respect what the codebase already does. A lone unfamiliar pattern is a
maintenance problem regardless of its merits.
- Give the simplest thing that solves the problem, then the pattern, and say
when the second beats the first.
Example of the standard I want
Weak: "Consider using the Strategy pattern here for better extensibility."
Strong: "Five branches on `type`, and you said two more are coming. A lookup
object keyed by type gets 90% of the benefit with none of the class
hierarchy. Reach for Strategy only if the branches gain state."
Output
Whether a pattern is warranted · the simplest fix · the pattern with its cost ·
when the pattern wins · fit with existing conventions.
The "without over-engineering it" constraint is the most important field in this prompt. Without it, models frequently recommend patterns that are theoretically correct but add abstraction layers that make a simple function harder to follow, not easier. The constraint forces the model to justify each pattern in terms of the actual complexity it reduces.
32. Dependency injection refactor
Use when you can't test something because it builds its own dependencies.
Role: Engineer introducing seams for testing, using the lightest mechanism
that works.
Context
- Code: [paste it]
- Hard dependencies: [what it constructs or imports directly]
- Why it matters: [testing, swapping implementations, environment differences]
- Framework: [any DI container in use, or none]
- Callers: [can they change?]
Task
Refactor for dependency injection.
Rules
- Use the smallest mechanism that solves it: a default parameter beats a
constructor argument, which beats a container. Introducing a DI framework for
three dependencies is a net loss.
- Don't create an interface with one implementation unless a second is genuinely
coming. "For testability" alone doesn't justify it — the concrete type can
usually be passed directly.
- Keep the common call site unchanged by defaulting to the real implementation.
- Note what becomes testable that wasn't, concretely.
- Watch for hidden dependencies too: clocks, randomness, environment variables
and global config are the ones that make tests flaky.
Example of the standard I want
Weak: "Inject the database dependency using an IoC container."
Strong: "`new Date()` at L15 is why the expiry test can't be written. Add
`now = () => new Date()` as a default parameter — callers unchanged,
and the boundary case becomes a one-line test."
Output
Refactored code with the lightest seam · call sites unchanged vs updated ·
hidden dependencies found · a test that was impossible before.
The "note what this enables for testing" instruction connects the refactoring to a concrete benefit. A developer who was not convinced a dependency injection refactor was worth doing will reconsider when they see the specific test scenarios it unlocks.
33. Error handling upgrade
Use when error handling grew by accretion and you want it coherent.
Role: Engineer redesigning error handling so failures are actionable rather
than merely caught.
Context
- Code: [paste it]
- Current approach: [try/catch, Result types, error codes, mixed]
- Failure modes: [what actually goes wrong in production]
- Who consumes errors: [end users, callers, operators, all three]
- Observability: [logging and alerting in place]
Task
Upgrade the error handling.
Rules
- Separate the three audiences: a user needs to know what to do next, a caller
needs to branch on the type, an operator needs enough context to debug.
Collapsing them is why error handling ends up useless to everyone.
- Distinguish expected failures (validation, not-found, conflict) from
unexpected ones. Expected failures are control flow, not exceptions to log at
error level.
- Preserve the cause when wrapping. Losing the original stack is a common and
costly mistake.
- Keep it consistent — one approach per layer, not three.
- Don't add retries without saying which failures are worth retrying and what
the backoff is.
Example of the standard I want
Weak: "Add better error handling with custom error classes."
Strong: "Three failure types share one generic Error, so callers string-match
messages to branch. Split into NotFound / Validation / Upstream;
callers branch on type, operator logs keep the cause."
Output
Error taxonomy for this code · handling per layer with audience · what to log
vs surface · cause preservation · retry policy where it applies.
The preservation constraint is critical when your error messages are part of a client contract. Changing "invalid_token" to a typed error class is a safe internal refactor; changing the string exposed to API consumers is a breaking change. The constraint explicitly prevents the model from conflating the two.
34. Type safety improvement
Use when runtime shape errors keep appearing in code that supposedly has types.
Role: Engineer strengthening types where they'd catch real bugs, not chasing
full coverage for its own sake.
Context
- Code: [paste it]
- Language/type system: [TypeScript strictness, Python hints, etc.]
- Runtime errors seen: [what actually breaks]
- Boundaries: [where untyped data enters — APIs, forms, env, storage]
- Constraints: [gradual migration? existing any usage?]
Task
Improve type safety.
Rules
- Prioritise boundaries. Types are assertions, not guarantees — data from an
API or a database is whatever it is, and typing it without validating is a
lie that makes the code feel safe.
- Recommend runtime validation at those boundaries with types derived from the
schema, so the two can't drift.
- Find `any`, unchecked casts and non-null assertions that hide real risk.
Rank by whether the value is externally controlled.
- Prefer making illegal states unrepresentable over adding checks — a union of
valid shapes beats four optional fields and a comment.
- Note where stricter typing would cost a lot of churn for little safety.
Example of the standard I want
Weak: "Replace `any` with proper types."
Strong: "`const user = await res.json() as User` asserts a shape nobody
verified — every downstream error traces here. Parse with a schema and
infer User from it; the cast disappears and drift becomes impossible."
Output
Boundary types that are assertions not guarantees · validation to add ·
unsafe casts ranked by exposure · states to make unrepresentable · what to skip.
The "explain what class of bug it prevents" instruction turns a mechanical annotation exercise into a code review artifact. The explanation is what makes a reviewer say "yes, this change is worth merging" rather than "I am not sure why we added 40 type annotations."
35. Dead code elimination
Use when you want to delete code and be confident nothing is calling it.
Role: Engineer removing dead code, careful about the ways "unused" is wrong.
Context
- Code: [paste the suspected dead code]
- Codebase scope: [what you can actually search — this bounds the claim]
- Public API: [is this exported or consumed externally]
- Tooling: [coverage data, static analysis, or nothing]
- Framework: [some frameworks call code by convention, not by reference]
Task
Assess what's safe to delete.
Rules
- Rate confidence per item and say what you couldn't check. Dynamic dispatch,
string-based lookup, reflection, template references, framework conventions
and DI registration all hide real usage from a text search.
- Anything exported from a package is reachable by consumers you can't see —
treat removal as a breaking change unless the scope says otherwise.
- Check tests, scripts, config and CI as call sites, not just application code.
- Note that git history preserves it, so deletion is recoverable — that's an
argument for deleting confidently once verified, not for skipping the check.
- Give the verification command per item.
Example of the standard I want
Weak: "These functions appear unused and can be removed."
Strong: "`formatLegacyDate` — no static references. But it's exported from the
package index, and the admin templates resolve helpers by string name,
which grep won't catch. Medium confidence: check templates before
removing."
Output
Items with confidence and reasoning · what you could not verify · verification
command per item · safe-now vs needs-checking · removal order.
When should I run separate review passes versus one combined prompt?
Separate targeted passes catch more issues per category than one combined prompt. The trade-off is time. A combined prompt is faster to run but produces shallower feedback across every dimension. Separate passes take longer but produce output that is easier to assign, track, and act on.
Run separate passes when:
- You are reviewing code before a security-sensitive deployment
- You are debugging a problem that has resisted one or more previous fixes
- You are preparing a codebase for a new contributor or open-source release
Run a combined prompt when:
- You need a quick sanity check on a small change before requesting a peer review
- You are doing an early-stage proof-of-concept review where good enough beats thorough
- Time is the binding constraint
For security reviews on any code that touches user data, authentication, or payment flows, separate passes are not optional. A combined prompt that touches security, performance, and readability simultaneously typically surfaces one or two findings per category. Three targeted passes surface significantly more coverage per category, and the output is organized by type, which makes it far easier to prioritize and assign.
How Prompt Architects fits this workflow
All 35 prompts above work inside ChatGPT, Claude, or Gemini without any additional setup. What Prompt Architects adds is the infrastructure that makes them reusable across reviews: save any prompt to your library with your language, framework, and output format pre-filled, and the next code review starts in ten seconds rather than requiring a fresh setup each time.
For teams running structured code reviews, the JSON prompt output format is particularly useful. Generate a machine-readable review report from a security or performance pass, then feed that output directly into your issue tracker or CI pipeline without reformatting. The JSON prompts guide explains the format in detail.
To carry your prompt library into your IDE, the MCP integration connects your saved prompts to Cursor and Claude Desktop so you can trigger a code review prompt without leaving your editor. Teams using MCP alongside a shared library are our most engaged users by a significant margin (our customer data, July 2026).
"The prompt library is genius — I save structured prompts by category and reuse them. Clean UI, no bloat. Just does the thing." — info.webefo, Verified AppSumo review
Prompt Architects is free to start, no credit card required. Add the Chrome extension and your saved review prompts are one click away inside whichever AI tool you have open.
Pick the five prompts that match your most common review bottleneck, save them with your stack details filled in, and run them on your next pull request. The setup time is under five minutes; the payback is in every review after that.
Generate structured JSON code review reports with Prompt Architects — free to start →