Updated July 2026Technique14 min read

Stop Claude Code from over-engineering: make it write less, simpler code

Ask an AI coding agent for email validation and you can get a 27-line class, a wrapper, and a regex that’s still wrong. Ask for a small feature and it installs a package, invents an abstraction, and hands you 200 lines where 50 would do. This is the most-felt complaint in the Claude Code community right now. Below: why agents over-build, and nine concrete, source-grounded techniques — copy-paste CLAUDE.md rules and prompts — to make them write the minimum the task actually needs.

Editorial illustration: on the left, a large tangled sprawling mass of stacked code-block shapes in warm amber, being distilled and pruned rightward into a single small clean minimal block glowing teal, on a deep midnight-navy background.
On this page · 19 sections
  1. TL;DR
  2. The "6x less code" moment
  3. Why agents over-build
  4. The fix: nine techniques
  5. 1. Demand the smallest change
  6. 2. Ban new dependencies
  7. 3. Match existing patterns
  8. 4. Write a YAGNI rule
  9. 5. The lazy-senior-dev framing
  10. 6. Ask for a plan first
  11. 7. Scope it, then verify
  12. 8. A simplify review pass
  13. 9. Diff-size discipline
  14. Paste-ready CLAUDE.md block
  15. What we got wrong
  16. The contrarian case
  17. Who this helps
  18. FAQ
  19. Sources

TL;DR

  • The pain is real and specific. Agents over-deliver: extra dependencies, speculative abstraction, drive-by refactors, 200 lines where 50 would do. It is the loudest recurring complaint in r/ClaudeCode.
  • The cause is the reward, not the model. An agent stops when the work looks done. Absent a scope constraint and a check it can run, the most complete-looking answer wins — and complete looks like more code.
  • The fix is prompt-and-config discipline. Negative, checkable CLAUDE.md rules; a plan before code; a simplify pass on the diff. A community skill built on exactly this reported ~54% less code across 12 tasks.
  • Do not overshoot. “Write less code” taken literally drops validation and safety checks. The rule is minimise scope, not correctness. Jump to the paste-ready CLAUDE.md block if you just want the template.

The “6x less code” moment

In mid-2026 a post titled “I gave Claude Code a ‘lazy senior dev’ mode and it writes like 6x less code” climbed to roughly 1,900 upvotes on r/ClaudeCode at a 98% upvote ratio. The opening line landed because every reader had lived it:

AI agents love to over-deliver. Ask for email validation and you get a 27-line EmailValidator class with a wrapper and a regex that's somehow still wrong.

r/ClaudeCode — I gave Claude Code a “lazy senior dev” mode · Reddit

~1,900 upvotes, 0.98 ratio, 183 comments. The thread that put a name to the over-engineering pain.

Source

The author’s fix was a skill that makes the agent walk a short ladder before writing anything: does this even need to exist? Does the standard library already do it? Is there a native platform feature? An existing dependency? Can it be one line? Only then does it write code, and only the minimum. The reported result: on one task a no-skill agent built a 190-line countdown “dashboard” with animations nobody asked for; the constrained agent shipped 13 lines. Across a 12-task benchmark, roughly 54% less code — and it never wrote more than the baseline.

This is not one person’s pet peeve. A separate r/ClaudeCode post — “Inherited a 3-month old repo from a Vibe Engineer” (7,300+ upvotes) — is the same pain at repo scale: an inherited codebase with 220 handlers of which about 20 were used, 40-plus secrets where two were needed, and 309k lines of code buried under 240k lines of docs. The author rewrote it smaller in a week, and drew the lesson bluntly: don’t build business logic “for the future,” because the future never arrives the way you imagined it.

220 handles, out of which only ~20 were used. 40+ secrets, out of which only 2 were necessary. 309k lines of code covered by 240k lines of docs.

r/ClaudeCode — Inherited a repo from a Vibe Engineer · Reddit

7,300+ upvotes. Over-engineering compounds: unused surface area becomes maintenance debt someone else pays down.

Source

Why agents over-build

Three mechanisms, none of which is “the model got dumber.” Naming them tells you which lever each technique below pulls.

“Looks done” is the only signal. Anthropic’s best-practices guide is explicit: “Claude stops when the work looks done. Without a check it can run, ‘looks done’ is the only signal available.” A model with no verification target and no scope ceiling reaches for the most complete-looking output it can justify — and completeness reads as more: more validation, more configuration, more defensive branches.

Vague prompts invite scope invention. The same guide notes Claude “can infer intent, but it can’t read your mind.” “Add a settings page” has a thousand valid expansions; the agent picks a generous one and fills the gaps with abstraction. As one commenter on the viral thread put it, the problem isn’t hidden logic, it’s “killing hallucinated scope” — left alone, the agent “will spin up an entire custom error hierarchy just to parse a basic string.”

Training rewards thoroughness. Models are tuned to be helpful and comprehensive. In prose that’s a virtue; in a diff it becomes the 27-line validator, the config option nobody requested, the “while I was here” refactor of an adjacent file. Andrej Karpathy’s widely cited diagnosis of LLM coding named it directly: they “really like to overcomplicate code and APIs, bloat abstractions… implement a bloated construction over 1000 lines when 100 would do.” Our line-by-line annotation of Karpathy’s CLAUDE.md walks the counter-rules in full.

The fix: nine techniques

Each technique below ships with a copy-paste artefact — a CLAUDE.md rule or a prompt — and the source it’s grounded in. They stack: rules set the default, prompts steer a single task, and a review pass catches what slipped through. You do not need all nine. Start with the CLAUDE.md rules (techniques 1–4), add the prompts when a task matters, and keep the simplify pass for anything headed to review.

1. Demand the smallest change

The single highest-yield rule. Make “minimum viable diff” the explicit default so the agent optimises for small instead of complete. Karpathy’s CLAUDE.md encodes the concrete heuristic: “If you write 200 lines and it could be 50, rewrite it.” A number the model can act on beats an adjective it can’t.

## Simplicity
- Prefer the smallest change that fully satisfies the request.
- If you wrote 200 lines and 50 would do, rewrite it as 50.
- Ask yourself: "Would a senior engineer call this overcomplicated?"
  If yes, simplify before showing me.

2. Ban new dependencies without asking

Unrequested packages are how a 10-line task becomes a supply-chain decision. The Vibe-Engineer repo above carried 40-plus secrets for two that mattered — every one of them a dependency someone added on the agent’s suggestion. Force a stop before the agent reaches for npm install.

## Dependencies
- Do NOT add a new dependency, package, or build step without asking first.
- Prefer the standard library and packages already in this project.
- If a dependency is genuinely needed, name it, say why, and wait
  for my go-ahead before installing.

3. Match existing patterns

Most over-engineering is the agent inventing a structure the codebase already has. Karpathy’s “Surgical Changes” principle is the counter: “Match existing style, even if you’d do it differently.” Point the agent at the canonical example first, and the new code inherits the codebase’s existing (usually smaller) shape instead of a greenfield one.

## Match what's here
- Before writing, find the closest existing pattern in this repo and
  match it — imports, error handling, file layout, naming.
- Do not introduce a new abstraction, helper, or config system if one
  already exists. Reuse it.
- When unsure which pattern is canonical, ask; don't invent a third.

4. Write a YAGNI rule

YAGNI — “you aren’t gonna need it” — is the rule against speculative flexibility. Karpathy’s file states it as four negatives, and negatives are easier to verify in a diff than any positive instruction: you can point at the config option nobody requested and delete it.

## YAGNI — no speculative building
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible states.

One caveat that the next few techniques and the contrarian section return to: “no error handling for impossible states” is wrong for auth, payments, and anything regulated, where the “impossible” case is a CVE in waiting. Scope this rule out of those paths.

5. The lazy-senior-dev framing

The framing that went viral works because it swaps the agent’s default persona — eager junior who proves effort by volume — for one that treats every line as a liability. Use it as a per-task prompt or as a saved skill. The load-bearing part is the ladder, not the personality.

Act like a senior engineer who writes the minimum. Before writing any
code, walk this ladder and tell me where you stop:

1. Does this need to exist at all?
2. Does the standard library already do it?
3. Is there a native platform feature for it?
4. Does an existing project dependency already do it?
5. Can it be one line?

Only write code past the first rung that genuinely needs it — and
write only the minimum. Keep validation and safety checks.

6. Ask for a plan first

The cheapest place to delete over-built code is before it exists. Anthropic’s recommended workflow is “explore first, then plan, then code,” because “letting Claude jump straight to coding can produce code that solves the wrong problem.” A plan surfaces the scope as three sentences you can trim, not 190 lines you have to review. In Claude Code, plan mode does this natively; in any agent, the prompt does it too.

Before writing any code, give me a short plan:
- the files you'll touch,
- the smallest approach that works,
- anything you're tempted to add that I didn't explicitly ask for.
Wait for my go-ahead before implementing.

7. Scope it, then verify

Two of the agent’s failure modes — solving the wrong problem and gold-plating the right one — both die when the prompt names the exact scope and a check that defines “done.” Anthropic’s own example is, tellingly, the same email-validation task the viral thread mocked — but scoped and checkable:

“write a validateEmail function. example test cases: [email protected] is true, invalid is false, [email protected] is false. run the tests after implementing.” — Anthropic, Claude Code best practices

A concrete check ends the loop the agent would otherwise fill with defensive code: it writes the function, runs the cases, and stops. No wrapper class, no speculative regex — the tests are the definition of enough.

Scope: implement <function> in <file> only. Do not touch other files.
Done = these cases pass: [case → expected, case → expected, ...].
Write the function, run the cases, show me the output. Nothing more.

8. A simplify review pass

Even a well-steered agent leaves fat. A dedicated second pass — a /simplify-style review that only hunts for deletion — catches it, and it’s the same senior-engineer self-check Karpathy’s file bakes in (“Would a senior engineer say this is overcomplicated?”). Run it on the diff, not the whole file, so it stays surgical.

Review this diff as a senior engineer whose only job is to cut.
- What can be deleted without changing behaviour?
- What abstraction has exactly one caller and should be inlined?
- What was added that I didn't ask for?
Do NOT remove any validation or safety check. Show me the smaller version.

If you run this pattern often, promote it from a pasted prompt to a saved skill so it loads on demand without bloating every session — the boundary our guide to Claude Code skills draws in detail.

9. Diff-size discipline

The falsification rule that ties the rest together is Karpathy’s: “Every changed line should trace directly to the user’s request.” It turns review into a mechanical check — point at any line that doesn’t trace, and it goes. Because CLAUDE.md rules are advisory, back the important limits with a hook: Anthropic notes hooks are “deterministic and guarantee the action happens,” unlike instructions the model can drift past.

## Surgical changes
- Every changed line must trace directly to my request.
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- If you notice unrelated dead code, mention it — don't delete it.

For hard limits — blocking edits to a directory, forcing a lint pass, capping what a single run may touch — a Claude Code hook is the enforceable version of a rule the model would otherwise treat as a suggestion.

The paste-ready CLAUDE.md block

Drop this into ./CLAUDE.md (or ~/.claude/CLAUDE.md for every project). It combines techniques 1–4 and 9 into one short block. Keep it short on purpose — Anthropic’s test for every line is “Would removing this cause Claude to make mistakes? If not, cut it,” and the guide warns that “bloated CLAUDE.md files cause Claude to ignore your actual instructions.”

## Write less, simpler code

**Default to the smallest change that fully solves the request.**
- If you wrote 200 lines and 50 would do, rewrite it as 50.
- No features, abstractions, config, or flexibility I didn't ask for.
- No error handling for impossible states (except auth/payments/security).
- No new dependency or package without asking first; prefer the stdlib
  and what's already installed.

**Match what's here.**
- Find the closest existing pattern and match it. Don't invent a new one.

**Stay surgical.**
- Every changed line must trace to my request.
- Don't refactor things that aren't broken or touch adjacent code.

Working signal: diffs get smaller, reviews get faster, and you ask a
clarifying question before building the wrong thing — not after.

That closing “working signal” line is deliberate: if after a week your diffs aren’t smaller, the file isn’t working and you should tune it. For the full anatomy of a good memory file, see Karpathy’s CLAUDE.md, annotated, and for where these rules belong versus a skill or an AGENTS.md, our CLAUDE.md vs AGENTS.md vs skills breakdown.

What we got wrong

Three things we had to unlearn tuning our own agents on this site — each one a technique above, learned the hard way.

We wrote “keep it simple” and thought that was a rule. It isn’t. “Write clean, simple code” is unfalsifiable — the agent already believes it’s doing that. Nothing changed until we replaced the adjective with checkable negatives (“no abstractions for single-use code,” “no new deps without asking”) and a number (“200 → 50”). Vague virtue rules are decoration; verifiable rules change diffs.

Then we overcorrected and told it to write one-liners. For a week our prompt was effectively “always write the fewest lines possible.” It did — and quietly dropped an input check on a path that took user data. We were not the first: the viral thread’s own benchmark found that a bare “just write one-liners” prompt missed a path-traversal guard the constrained skill kept. The lesson rewrote every rule above to say the same thing: minimise scope, never correctness. “Keep validation and safety checks” is not optional boilerplate; it is the clause that makes the technique safe to ship.

We blamed the model for a pattern it never saw. We kept getting a bespoke fetch wrapper when the repo already had one. The agent wasn’t being clever; we never showed it the existing helper, so “match the pattern” had no pattern to match. Pointing it at the canonical file first — technique 3 — deleted the whole class of duplicate abstraction overnight. Most “the agent over-engineered” moments are really “I under-specified.”

The contrarian case

Not everyone thinks “make it write less code” is the right frame — and the objections are worth keeping.

Sometimes the extra code is right. The most upvoted skeptical reply to the lazy-senior-dev post made the point with the exact example the thread opened on:

This works great... if you're planning on sending the email. If not, you've just introduced a bug that allows users to save invalid emails to your database. Whoops!

SwiftEngineer — top reply · Reddit

The counter-case: some of the code the agent adds is the code you needed. A validator is bloat until the day it isn't.

Source

A second commenter generalised it: “Write less code is often not a good solution (implicit vs explicit). You will miss stuffs, cases and error messages will be very generic. Also debugging is a pain.” Terse code can be harder to debug and quietly drop the edge cases explicit code spells out. This is why every rule above carves out validation and safety.

And maybe the persona is a crutch for an under-specified prompt. The sharpest critique argued this is a prompting-skill problem in disguise: dressing the request up as a “lazy senior dev” only “pollutes the context with information that doesn’t contribute to solving the problem,” because the model now has to decode the persona before it can act. If you can name precisely what you want — scope, files, the check for “done” — you don’t need the costume. We think both are true: technique 7 (scope + verify) is the precise-prompt path, and the persona is a fast heuristic for when you can’t be bothered to write the precise version. Reach for the costume when you’re moving fast; reach for the spec when the code matters.

The honest synthesis: over-engineering is not a model defect to be suppressed, it is a scope-and-verification gap to be closed. Close it with a precise prompt and a check, and the “write less” behaviour falls out for free — without a persona and without dropping the guard rails.

Who this helps

This is for you if you review agent PRs and keep deleting code that shouldn’t have been written; if a one-line ask keeps returning a 200-line diff; if your agent installs packages you didn’t sanction or reinvents helpers you already have; or if you maintain a codebase where surface area is the enemy.

This is less urgent if you’re prototyping to explore a design space (over-building is sometimes how you find the shape), or writing throwaway scripts where a 190-line dashboard that works is fine and review time is zero. The techniques still work; the payoff is just smaller when nobody has to maintain the output. For the broader operating manual, our Claude Code best practices covers session hygiene and context management, and if the agent feels off in a way rules don’t fix, the 2026 quality postmortem separates a real regression from your own prompt drift. You can also wire these habits into Claude Code directly.

Frequently asked questions

Why does Claude Code write so much code?

Agents optimise for looking complete, not minimal. Given a vague task, the safest-looking answer adds validation, config, and abstraction you never asked for. Anthropic's own guidance notes that without a check it can run, "looks done" is the only signal the agent has. Constrain the scope and give it a verification target, and it stops over-building.

How do I make Claude Code write less code?

Put negative, checkable rules in CLAUDE.md ("no new dependencies without asking," "match existing patterns," "every changed line must trace to the request"), ask for a plan before code, and run a simplify pass on the diff. One r/ClaudeCode skill reported roughly 54% less code across 12 tasks using exactly this framing.

What is the "lazy senior dev" prompt?

A framing that tells the agent to behave like a senior engineer who writes the minimum: check whether the thing needs to exist, whether the standard library or a native feature already does it, whether it can be one line — and only then write code. It went viral on r/ClaudeCode (around 1,900 upvotes) as a "lazy senior dev" mode.

Does telling Claude to write less code cause bugs?

It can, if you strip checks that matter. Commenters on the viral thread noted a naive "one-liner only" prompt dropped an email-validation check, and in the author's own benchmark a bare version missed a path-traversal guard. The fix is "write less code, but keep the validation and safety checks" — minimise scope, not correctness.

Should over-engineering rules go in CLAUDE.md or a skill?

Always-on behavioural rules — simplicity, no new deps, surgical changes — belong in CLAUDE.md because they apply to every task. A repeatable "simplify this module" workflow belongs in a skill so it loads on demand. Keep CLAUDE.md short: Anthropic warns that bloated files get ignored.

Is over-engineering the model's fault or mine?

Mostly the prompt's. One contrarian on the viral thread argued that cute personas "pollute the context" and that you should name the problem precisely instead. Both can be true: a scoped prompt with a verification check beats both a vague request and a clever persona.

What's the single highest-leverage change?

Ask for a plan before it codes, and give it a verification check. Anthropic calls verification "the single highest-leverage thing you can do." A plan surfaces the scope before it is written, so you delete the dashboard nobody asked for in three sentences of review, not 190 lines of diff.

Do

Set checkable negative rules, ask for a plan, scope the task with a verification check, and run a simplify pass on the diff. Minimise scope.

Don’t

Write vague “keep it simple” rules, demand raw one-liners, or strip validation and safety checks in the name of fewer lines. Never minimise correctness.

Sources

Community (verified via r/ClaudeCode)

Primary (docs & first-party)

  • Anthropic — Claude Code best practices — “Claude stops when the work looks done,” “explore first, then plan, then code,” the validateEmail verification example, the “would removing this cause mistakes?” test, the bloated-CLAUDE.md warning, and hooks being deterministic.
  • forrestchang/andrej-karpathy-skills — the Simplicity First and Surgical Changes principles (“200 lines could be 50,” “every changed line should trace to the request”) quoted throughout, distilled from Karpathy’s LLM-coding thread.

Related on mcp.directory

Keep reading