Claude: Avoid Over-engineering

A system-prompt snippet telling Claude to make only requested or necessary changes: no extra features, refactors, comments, defensive code or abstractions.

  • 🤖 Claude
  • 🗂️ Coding

Prompt by Anthropic — Claude prompting best practices · Original source (opens in a new tab)

Claude: Avoid Over-engineering — illustration

The prompt

prompt
Avoid over-engineering. Only make changes that are directly requested or clearly
necessary. Keep solutions simple and focused:

- Scope: Don't add features, refactor code, or make "improvements" beyond what was
asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need
extra configurability.

- Documentation: Don't add docstrings, comments, or type annotations to code you didn't
change. Only add comments where the logic isn't self-evident.

- Defensive coding: Don't add error handling, fallbacks, or validation for scenarios
that can't happen. Trust internal code and framework guarantees. Only validate at system
boundaries (user input, external APIs).

- Abstractions: Don't create helpers, utilities, or abstractions for one-time
operations. Don't design for hypothetical future requirements. The right amount of
complexity is the minimum needed for the current task.

What it is

A short prompt block that instructs Claude to avoid over-engineering when working on code. It sets four rules: stay within the requested scope, don't add docs or annotations to code it didn't change, don't add defensive handling for scenarios that can't happen, and don't create abstractions for one-time operations or hypothetical future needs. The stated goal is the minimum complexity needed for the current task.

Who it's for

  • Developers using Claude as a coding agent who want small, reviewable diffs
  • Teams whose agents tend to refactor, add configuration options or sprinkle extra comments
  • Prompt authors writing system prompts for coding assistants

Requirements

Requirements

  • Access to Claude through a setup where you can supply instructions (e.g. a system prompt or the start of a task prompt)
  • A coding task or codebase for the agent to work on

Examples

Bug fix without surrounding cleanup

Prompt
prompt
Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused:

- Scope: Don't add features, refactor code, or make "improvements" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability.

- Documentation: Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.

- Defensive coding: Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs).

- Abstractions: Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task.

Task: In utils/pricing.py, the function apply_discount returns a negative total when the discount is larger than the subtotal. Fix it so the total never goes below zero.

Expected output: Claude should make a minimal edit to apply_discount (e.g. clamp the total at zero) without renaming, reformatting or documenting the rest of the file.

Simple feature without extra configurability

Prompt
prompt
Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused:

- Scope: Don't add features, refactor code, or make "improvements" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability.

- Documentation: Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.

- Defensive coding: Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs).

- Abstractions: Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task.

Task: Add a "Export to CSV" button to the orders page in our React app that downloads the currently displayed orders table as a CSV file.

Expected output: Claude should add the button and the export logic for the current table only, without a generic export framework, format options or settings.

Internal call vs. system boundary validation

Prompt
prompt
Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused:

- Scope: Don't add features, refactor code, or make "improvements" beyond what was asked. A bug fix doesn't need surrounding code cleaned up. A simple feature doesn't need extra configurability.

- Documentation: Don't add docstrings, comments, or type annotations to code you didn't change. Only add comments where the logic isn't self-evident.

- Defensive coding: Don't add error handling, fallbacks, or validation for scenarios that can't happen. Trust internal code and framework guarantees. Only validate at system boundaries (user input, external APIs).

- Abstractions: Don't create helpers, utilities, or abstractions for one-time operations. Don't design for hypothetical future requirements. The right amount of complexity is the minimum needed for the current task.

Task: Add a new POST /api/signup endpoint that takes an email and password from the request body and calls our existing create_user(email, password) service function.

Expected output: Claude should validate the request body at the endpoint (a system boundary) but not re-validate inside the internal create_user call or add speculative fallbacks.

Pros & cons

Pros

  • Pro:Keeps changes limited to what was asked, which makes diffs easier to review
  • Pro:Discourages unrequested refactors and "improvements" in bug fixes
  • Pro:Avoids comment, docstring and type annotation noise on untouched code
  • Pro:Cuts unnecessary error handling and validation for impossible scenarios while still allowing validation at system boundaries
  • Pro:Discourages one-off helpers and speculative design for future requirements

Cons

  • Con:May leave genuine nearby problems unaddressed, since the prompt discourages going beyond the request
  • Con:Relies on Claude's judgment of what is "clearly necessary" or "self-evident", which the prompt doesn't define precisely
  • Con:Not suited to tasks where you actually want refactoring, broader documentation or extensibility, unless you adjust the rules

Tips

  • Put the block in the system prompt so it applies to every coding task in the session
  • Make your task request specific, since the prompt limits work to what is directly requested
  • Remember the carve-outs: comments are still fine where logic isn't self-evident, and validation is still expected at system boundaries such as user input and external APIs
  • If you do want a refactor or extra feature, say so explicitly in the task so it counts as requested

Variations

  • Keep only the Scope bullet for a lighter version that targets unrequested features and refactors
  • Drop the Documentation bullet if your team does want docstrings or type annotations added
  • Add a sentence listing which of your boundaries count as system boundaries (for example, your public API and third-party integrations)
  • Invert a rule for a specific task, e.g. explicitly request a refactor of one named module while keeping the other rules