Over-Engineering Guard
Holds an agent to the smallest solution that actually works: a seven-rung ladder it climbs before writing anything, a named ceiling on every shortcut it takes deliberately, and a short list of things it is never allowed to simplify away.
What it does
Runs every coding task through a ladder that stops at the first rung that holds. Does the thing need to exist at all, is there already a helper or pattern in this codebase, does the standard library cover it, does a native platform feature cover it (a date input rather than a picker dependency, CSS rather than JavaScript, a database constraint rather than application code), does an already-installed dependency cover it, can it be one line, and only then the minimum code that works. The ladder runs after comprehension rather than instead of it: the rule is to trace every file the change touches and the real flow end to end before picking a rung, because the smallest change in the wrong place is a second bug rather than a lazy win. A bug fix is held to the root cause, so the callers of the function about to be edited get grepped first and one guard lands in the shared path instead of in the single caller the ticket happened to name. Three intensity levels set how hard it pushes: lite builds what was asked and names the lazier alternative in one line, full enforces the ladder, ultra ships the one-liner and questions the rest of the requirement in the same response. An exclusion list is never negotiable, covering input validation at trust boundaries, error handling that prevents data loss, security measures, accessibility basics, and anything explicitly requested. Corner-cutting is not left implicit either: a simplification with a real ceiling (a global lock, a quadratic scan, a naive heuristic) carries a comment naming that ceiling and the upgrade path, and those comments can be harvested later into one ledger so a deferral does not quietly turn permanent. Non-trivial logic leaves exactly one runnable check behind, the smallest thing that fails if the logic breaks. Output is code first, then at most three lines naming what was skipped and when to add it. Distilled from DietrichGebert/ponytail (MIT, v4.9.0, 131,991 stars and 7,068 forks), whose published agentic benchmark measures 54 percent less code, 22 percent fewer tokens and 27 percent less wall-clock against the same agent with no skill across twelve feature tasks, with the adversarial safety tier held at 100 percent.
When to use
- ✓An agent answered a twenty-line requirement with an interface, a factory, a config layer and a base class, and none of it was asked for
- ✓A dependency is about to be added for behaviour the standard library or the browser already covers
- ✓A fix landed on the one path the ticket named and every sibling caller stayed broken
- ✓Review keeps turning into the same argument about flexibility that no ticket has ever needed
- ✓You want the deliberate shortcuts in a codebase collected and read back, rather than discovered a year later
When not to use
- ✗The quality bar itself needs deciding and writing down: use constraint-driven-development, which sets what good enough means rather than how much gets built
- ✗You want a correctness review: use code-review-helper, which hunts bugs, while this one only hunts excess and will happily approve code that is small and wrong
- ✗Existing code needs restructuring rather than a new change kept small: use refactor-planner
- ✗The task is genuinely irreducible, such as a protocol implementation or a compliance requirement where every branch is mandated: the ladder will burn a round arguing with a spec that already decided
- ✗Prose, documentation, or a walkthrough the reader asked for in full: this governs what gets built, never how much you explain when explanation was the request
Install
Download the .zip, then unzip into your Claude skills folder.
mkdir -p ~/.claude/skills
unzip ~/Downloads/over-engineering-guard.zip -d ~/.claude/skills/
# Restart Claude Code session.
# Skill is now available — Claude will use it when relevant.SKILL.md
---
name: over-engineering-guard
description: Use when an agent builds more than the task needs, such as a speculative abstraction, a dependency for something the platform already does, or a config layer for a value that never changes. Triggers on "simplest thing that works", "stop over-engineering", "YAGNI", "do less", "what can we delete", "is this over-engineered", or a complaint about bloat and boilerplate. Governs how much gets built. Not a correctness review, and not the place to decide the project quality bar.
---
# Over-Engineering Guard
An agent writes fast enough that the expensive mistake is no longer a typo, it is a hundred lines that never needed to exist. Those lines get reviewed, tested, documented and maintained by someone who did not ask for them. The cheapest code to own is the code that was never written, and the second cheapest is the code the platform already wrote for you.
This is a discipline applied while building, not a cleanup pass afterwards.
## The ladder
Before writing, climb. Stop at the first rung that holds.
1. **Does this need to exist at all?** A speculative need is not a requirement. Skip it and say so in one line.
2. **Does this codebase already have it?** A helper, a type, a util, a pattern living a few files over. Re-implementing what already exists is the most common form of the problem.
3. **Does the standard library do it?** Use it.
4. **Does a native platform feature cover it?** A date input over a picker dependency. CSS over JavaScript. A database constraint over application code.
5. **Does an already-installed dependency solve it?** Use that. Never add a new one for what a few lines cover.
6. **Can it be one line?** Then it is one line.
7. **Only now:** the minimum code that works.
Two rungs both work? Take the higher one and move on. The first solution that holds is the right one.
## Comprehension is not on the ladder
The ladder shortens the solution. It never shortens the reading.
Read the task and the code it touches, trace the real flow end to end, and only then climb. A minimal diff in the wrong place is not laziness, it is a second bug wearing the costume of efficiency. This is the failure mode worth naming out loud, because it looks like exactly the behaviour you asked for.
The same applies to fixes. A report names a symptom. Grep every caller of the function before editing it: one guard in the shared function is a smaller diff *and* the correct fix, where a patch on the single named path leaves every sibling caller broken and the ticket reopened.
## What is never simplified away
No rung of the ladder reaches these:
- Input validation at trust boundaries
- Error handling that prevents data loss
- Security measures
- Accessibility basics
- Anything explicitly requested
Between two standard-library options of the same size, take the one that is correct on edge cases. Writing less code is the goal; picking the flimsier algorithm is not. And when someone asks for the full version after hearing the lazy one, build it without re-arguing.
## Rules that follow from the ladder
- No interface with one implementation, no factory for one product, no config for a value that never changes.
- No scaffolding for later. Later can scaffold for itself.
- Deletion beats addition. Boring beats clever, because clever is what somebody decodes at three in the morning.
- Fewest files that work.
- If the explanation defending a simplification runs longer than the code, the complexity came back as prose.
## Intensity
| Level | Behaviour |
|---|---|
| **lite** | Build what was asked, name the lazier alternative in one line, let the user choose. |
| **full** | The ladder enforced. Standard library and native platform first. Shortest working diff. The default. |
| **ultra** | Deletion before addition. Ship the one-liner and challenge the rest of the requirement in the same breath. |
Take a request for a cache. Under lite the cache gets built, with a note that a memoisation decorator from the standard library covers it in one line. Under full the decorator goes on the fetch function and the custom cache class is skipped. Under ultra there is no cache until a profiler asks for one.
## Mark the corners you cut on purpose
A shortcut with a known ceiling is a decision, not an accident, and it should read as one. Leave a comment naming the ceiling and the upgrade path: a global lock that becomes per-account locks if throughput matters, a quadratic scan that holds until the list grows, a heuristic that works until the input stops being well-formed.
Those comments are the ledger. Harvest them on demand and a deliberate deferral cannot quietly become permanent, which is the usual fate of the word "later".
## One check, not a suite
Non-trivial logic (a branch, a loop, a parser, anything touching money or auth) leaves behind the smallest runnable thing that fails if the logic breaks. One assertion-based self-check or one small test file. No fixtures, no per-function suites unless asked.
Trivial one-liners need no test. The rule applies to tests too.
## Delivering
Code first. Then at most three short lines, in the shape: what was skipped, and when to add it.
No feature tour, no design notes, no essay on the philosophy of the change. If the user asked for a report or a walkthrough, give it in full, because requested explanation is not debt. The rule is only against prose nobody wanted.
## Where this ends
The guard is finished when the diff is the shortest one that solves the understood problem, every remaining line traces to something asked for or something the exclusion list protects, each deliberate ceiling carries its comment, and the skipped work is named in a line the user can act on. If it produced a small diff by reading less, it failed, whatever the line count says.
Example prompts
Once installed, try these prompts in Claude:
- Before writing anything for this ticket, walk the ladder out loud: does this need to exist at all, is there already a helper in this repo, does the standard library or a native platform feature cover it, and can it be one line. Trace the files the change touches first, then build the rung you land on and tell me in three lines what you skipped and when I should add it.
- Review this diff for over-engineering only, not correctness. One line per finding: file and line, what to cut, what replaces it. Flag every interface with a single implementation, every config value that never changes, every scaffold added for later, and every new dependency doing something the standard library already does.
- Collect every deliberate shortcut comment in this repository into one ledger, grouped by ceiling, and tell me which ones now have real traffic behind them and should be upgraded.
- Sep 8, 2026New skill: a seven-rung ladder climbed before writing, comprehension held off that ladder so a small diff never substitutes for tracing the flow, three intensity levels, an exclusion list covering validation, data loss, security and accessibility, and a named ceiling on every deliberate shortcut.