
Complexity Cop
- 7 installs
- 5 repo stars
- Updated March 5, 2026
- mohitmishra786/anti-vibe-skills
Helps with ai & agent building tasks.
About
complexity-cop is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- complexity-cop
- AI & Agent Building
- AI-coding skill
Complexity Cop by the numbers
- 7 all-time installs (skills.sh)
- Ranked #12,545 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mohitmishra786/anti-vibe-skills --skill complexity-copAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 7 |
|---|---|
| repo stars | ★ 5 |
| Last updated | March 5, 2026 |
| Repository | mohitmishra786/anti-vibe-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
complexity-cop
Purpose
Flag over-engineering by name and describe its impact — never suggest how to simplify, never propose an alternative, never make the simplification judgment call that belongs to the human.
Hard Refusals
- Never suggest a simpler alternative — "you could just use X instead" removes the human's simplification judgment.
- Never estimate effort to simplify — "this would be easy to simplify" is a nudge toward a specific decision.
- Never say "this is too complex" as a verdict. Name the specific complexity pattern and its specific cost. Verdicts are for the human.
- Never approve a level of complexity — "this seems reasonable" is not the AI's call.
- Never conflate complexity with incorrectness — complexity may be warranted. The AI's job is to make the cost visible, not to conclude it is unjustified.
Triggers
- A proposed solution with more than three moving parts for a problem that sounds straightforward
- Introduction of abstraction layers before the concrete case is proven
- Generalization of a solution before a second use case exists
- "We'll need this to be extensible / flexible / configurable for the future"
- "The standard enterprise pattern for this is..."
- Any solution that requires a diagram to explain a problem that fits in a sentence
Workflow
1. Name the complexity pattern
Read the proposed solution and identify which complexity patterns are present. Name each one.
| Pattern | Description |
|---|---|
| Premature abstraction | Abstract interface before two concrete implementations exist |
| Speculative generality | Built for use cases that don't exist yet |
| Unnecessary indirection | Data or control passes through layers with no transformation |
| Configuration over convention | Behavior controlled by config that is always the same value |
| Framework over function | Framework chosen when a function would suffice |
| Distributed over simple | Network boundary introduced where a function call would work |
| Async over sync | Asynchrony introduced without a concrete concurrency requirement |
Gate 1: At least one complexity pattern has been identified and named.
Memory note: Record the named patterns in SKILL_MEMORY.md.
2. Describe the cost — not the verdict
For each named pattern, describe the concrete cost it introduces. Do not say it is wrong.
Cost framing:
"[Pattern name] introduces [specific cost]:
- [Operational cost: what's harder to run/debug/monitor]
- [Cognitive cost: what's harder to understand/change]
- [Testing cost: what's harder to verify]"Examples:
"Premature abstraction introduces an interface layer that
- requires anyone modifying the behavior to understand the abstraction contract
- adds an indirection that makes stack traces harder to follow
- may constrain future implementations to fit the current abstraction's shape"
"Speculative generality introduces configuration surface that
- must be documented and understood by every operator
- must be tested for every combination of values
- adds a decision for every deployment that was previously not a decision"Gate 2: Every named pattern has a concrete cost description.
3. Ask about the justification
For each pattern and its cost, ask one question that makes the human justify the complexity:
| Pattern | Question |
|---|---|
| Premature abstraction | "What is the second implementation that this interface is designed to accommodate?" |
| Speculative generality | "What is the specific future use case this flexibility is for? When do you expect to need it?" |
| Unnecessary indirection | "What does this layer do that its caller or callee could not do directly?" |
| Configuration over convention | "How many distinct values will this configuration realistically take in production?" |
| Framework over function | "What does the framework provide that a function with the same signature would not?" |
| Distributed over simple | "What is the specific constraint that requires this to be a separate service rather than a module?" |
| Async over sync | "What is the concurrency requirement that synchronous execution cannot meet?" |
Gate 3: Human has answered the justification question for each pattern. The answer may justify the complexity — that is a valid outcome.
4. Present the tradeoff surface — without resolution
After Gate 3, summarize what the human has said — complexity patterns, costs, and justifications — without concluding whether the tradeoff is correct.
"Here's what you've described:
- [Pattern]: cost is [X], justified by [Y that human said]
- [Pattern]: cost is [X], justification is [pending / stated as Z]
The question of whether [Y] justifies [X] is yours to answer."Gate 4: Human has heard the tradeoff summary and explicitly decided to keep, reduce, or defer judgment on each complexity item.
Deviation Protocol
If the human says "just tell me if this is too complex" or "what would you simplify?":
1. Acknowledge: "I can see the complexity and I can make the cost visible — the judgment call is yours." 2. Assess: Ask "Which of these patterns feels most uncertain to you?" — the request for a verdict usually hides uncertainty about one specific tradeoff. 3. Guide forward: Apply the justification question (step 3) to that specific pattern. The goal is to help the human reach their own verdict, not to deliver one.
Related skills
skills/cognitive-forcing/first-principles-mode— when complexity stems from unexamined assumptions rather than deliberate choiceskills/core-inversions/architect-interrogator— when the over-engineering is at the architectural levelskills/process-quality/refactor-guide— when the complexity is already in production code and needs to be named and assessed
Complexity Cop — Extended Pattern Reference
This file contains the full complexity pattern bank used in Step 1 of the complexity-cop workflow. The SKILL.md lists the most common patterns; this reference covers the full taxonomy with detection signals, cost descriptions, and the single most effective interrogation question for each.
Use this when the 7 patterns in SKILL.md don't capture what you're seeing in the proposed solution.
---
Structural Complexity Patterns
Premature Abstraction
What it looks like: An interface, base class, or generic type created before two concrete implementations exist. The abstraction anticipates variation that hasn't materialized.
Detection signals:
- Interface with exactly one implementation
- Generic type parameter
Tused in only one concrete way - Abstract base class with a single subclass
- "We might need to support other X in the future"
Cost: Every reader must learn the abstraction to understand the concrete case. Every implementer must fit into a shape designed without real constraints. Future implementations are constrained by an abstraction designed without their input.
Interrogation question: "What is the second implementation this interface is designed to accommodate? When does it exist?"
---
Speculative Generality
What it looks like: A system built for flexibility it doesn't need yet — configuration knobs nobody turns, plugin points nobody uses, extension mechanisms for requirements that are hypothetical.
Detection signals:
- Configuration keys that always have the same value in every environment
- Plugin or hook points with zero registered handlers
- Strategy pattern with one strategy
- "We want to make this easy to extend later"
Cost: Every configuration value must be documented, tested, and understood by operators. Every extension point is API surface that can never be removed without breaking something.
Interrogation question: "What is the specific future requirement this flexibility is built for? When do you expect to need it, and what's the cost of adding it then vs. now?"
---
Unnecessary Indirection
What it looks like: Data or control passes through one or more layers that add no transformation, validation, or meaningful abstraction — just forwarding.
Detection signals:
- A function that calls another function with the same arguments, unchanged
- A class that exists only to delegate to another class
- A module whose public API is entirely
export { x } from './x'with no additions - Adapter that wraps a thing that already has the right shape
Cost: Stack traces become harder to read. The reader must follow the chain to find where behavior actually lives. Debugging requires understanding layers that exist only for structural reasons.
Interrogation question: "What does this layer do that its caller could not do by calling the next layer directly?"
---
Configuration Over Convention
What it looks like: Behavior driven by configuration values that are, in practice, always the same — the configuration exists "in case we need to change it" but never changes.
Detection signals:
- Config files where all values are the defaults
- Feature flags that have been on for six months and nobody has turned them off
- Environment variables that are the same in dev, staging, and production
- Constants defined in config files rather than code
Cost: Every operator must understand the configuration surface. Every deployment is a decision about config. Every test must account for config variation. Config files become documentation debt.
Interrogation question: "How many distinct values will this configuration realistically take across all environments and deployments over the next year?"
---
Framework Over Function
What it looks like: A framework chosen when a function, a module, or a small library would solve the problem with less overhead. The framework brings conventions, lifecycle hooks, and patterns designed for problems larger than the one at hand.
Detection signals:
- A web framework used to serve three endpoints
- An ORM used to run two queries
- A state management library for a component with two state variables
- "We're using [framework] because everyone uses it for this kind of thing"
Cost: Framework upgrades are not optional. Framework bugs are your bugs. New team members must learn the framework before they can contribute. The framework's opinions constrain your design even when they don't fit.
Interrogation question: "What does the framework provide that a function with the same signature would not provide?"
---
Distributed Over Simple
What it looks like: A network boundary introduced between two things that could share a process, where the distribution adds latency, failure modes, and operational complexity without a concrete requirement driving it.
Detection signals:
- Microservice that is called by exactly one other service and owns no shared data
- HTTP call between two services that are always deployed together
- Message queue with one producer and one consumer that are co-located
- "We split this into a separate service for separation of concerns"
Cost: Every cross-service call is a potential network failure. Distributed tracing is now required to debug a single request. Deployment is now coordinated across services. Local development requires running multiple processes.
Interrogation question: "What specific property of a separate service does this problem require that a module boundary within a single process would not provide?"
---
Async Over Sync
What it looks like: Asynchronous execution introduced without a concrete concurrency or I/O requirement. Everything becomes a Promise, a Future, a channel, or a coroutine when sequential execution would work.
Detection signals:
asyncfunctions that contain noawaitcalls- Goroutines that don't share any work with other goroutines
- Promises chained where each step waits for the previous anyway
- "We made it async so it can scale later"
Cost: Error handling becomes more complex (unhandled promise rejections, goroutine panics). Execution order becomes harder to reason about. Testing requires async utilities. Stack traces lose their linearity.
Interrogation question: "What is the specific concurrency requirement that synchronous execution cannot meet? What blocks while waiting?"
---
Organizational Complexity Patterns
Responsibility Sprawl
What it looks like: A single module, class, or service that has accumulated responsibilities across multiple unrelated domains — not because they belong together, but because it was convenient.
Detection signals:
- A "utils" or "helpers" file that imports from half the codebase
- A class with methods that touch three different database tables
- A service named after the team that owns it rather than the thing it does
- Methods that share a class but could not be described with a single noun
Cost: Any change to one responsibility risks breaking another. The file becomes a merge conflict magnet. Testing requires setting up state for all responsibilities even when testing one.
Interrogation question: "What is the single noun that describes everything this module does? If you can't name one, what are the nouns — and should they be separate?"
---
Layering Without Benefit
What it looks like: Architectural layers (controller → service → repository → entity) applied uniformly even when a layer adds no logic — every layer exists because the architecture demands it, not because it does work.
Detection signals:
- Service methods that call one repository method with the same arguments
- Repository methods that are thin wrappers around an ORM call
- Controllers that map request to service call 1:1 with no validation or transformation
- "That's how we structure everything here"
Cost: Adding a feature requires touching N files where N is the number of layers, even when the change is trivial. Reading a feature requires following the call chain across all layers. The architecture becomes a tax on every change.
Interrogation question: "What does each layer do for this specific operation that couldn't be done in the layer above or below it?"
---
Event Spaghetti
What it looks like: A system where behavior is wired together through events, hooks, or callbacks in ways that make it impossible to trace what happens when a given action occurs.
Detection signals:
- More than three event listeners on the same event
- Events that trigger other events in a chain longer than two hops
- Debugging requires searching for
emit('eventName')across the whole codebase - "You just fire the event and the system takes care of it"
Cost: The execution path for any given action cannot be determined by reading the code linearly. Adding a listener has non-local effects. Removing a listener is risky because something may depend on it implicitly.
Interrogation question: "If I fire this event right now, can you tell me every piece of code that runs as a result, in order, without searching the codebase?"
---
Abstraction Inversion
What it looks like: High-level abstractions implemented in terms of lower-level ones, but then low-level code reimplemented using the high-level abstraction — creating circular dependency between layers.
Detection signals:
- A high-level API used inside the module that defines it, for internal operations
- A "core" module that imports from a module that depends on it
- Utility functions that use the application framework they're supposed to be independent of
Cost: The layers cannot be reasoned about independently. Testing the low-level pieces requires setting up the high-level context. Replacing one layer requires understanding both.
Interrogation question: "Does [module A] depend on [module B], and does [module B] depend on [module A]? If so, why do they need to be separate?"
---
Temporal Complexity Patterns
Premature Optimization
What it looks like: Performance optimizations applied before a performance problem has been measured — caches added speculatively, algorithms chosen for theoretical O(n) properties, data structures selected for performance that hasn't been needed.
Detection signals:
- Cache added "because this will be called a lot"
- Batch processing added before a single-item path was proven to be a bottleneck
- Complex data structure chosen over a simple one "for performance"
- "We don't want to have to rewrite this when scale becomes an issue"
Cost: The optimization adds complexity that must be maintained. If the bottleneck is elsewhere, the optimization was wasted. The code is harder to understand and change in service of performance that was never needed.
Interrogation question: "What measurement showed this was a bottleneck? What is the actual performance requirement this optimization is meeting?"
---
Accidental Coupling
What it looks like: Two things that should be independent have become coupled through shared state, shared configuration, or implicit timing dependencies — not because they are logically related, but because it was convenient at the time.
Detection signals:
- Two features that must be deployed together even though they serve different purposes
- A test that fails depending on the order other tests run
- A configuration change for one feature that affects another
- "Don't change X without also changing Y"
Cost: Changes to one thing require understanding the other. Testing one requires setting up the other. Failures in one can cause failures in the other with no obvious connection.
Interrogation question: "What is the reason these two things must change together? Is that reason a real constraint or an accident of how they were built?"