Code Simplification

Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read…

You say
Install this skill Read the source first Free Written by addyosmani · unverified publisher
Context cost
3.4k tokensestimated from the bundle, loaded when it triggers
Bundle
1 file · 13.5 kBtext throughout, nothing executable
Licence
MITfree to use
Last change
no release on file
Servers it uses
Noneruns standalone

What it does

Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read, maintain, or extend than it should be. Use when reviewing code that has accumulated unnecessary complexity.

Installed, it changes the agent in these ways.

What this skill changes about the agent is not written down here yet. The listing was collected from its source, and the description is in its own SKILL.md.

Workflow

Runs a procedure end to end.

developer toolsrefactoring

The skill itself

This is the whole product. A skill is instructions the model reads, so there is nothing behind the listing you cannot see first — the front matter loads with every session, and the body below it loads when the skill triggers.

SKILL.md13.5 kB · 332 lines
--- name: code-simplification description: Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read, maintain, or extend than it should be. Use when reviewing code that has accumulated unnecessary complexity. ---
6# Code Simplification
7
8> Inspired by the [Claude Code Simplifier plugin](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/code-simplifier/agents/code-simplifier.md). Adapted here as a model-agnostic, process-driven skill for any AI coding agent.
9
10## Overview
11
12Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass a simple test: "Would a new team member understand this faster than the original?"
13
14## When to Use
15
16- After a feature is working and tests pass, but the implementation feels heavier than it needs to be
17- During code review when readability or complexity issues are flagged
18- When you encounter deeply nested logic, long functions, or unclear names
19- When refactoring code written under time pressure
20- When consolidating related logic scattered across files
21- After merging changes that introduced duplication or inconsistency
22
23**When NOT to use:**
24
25- Code is already clean and readable — don't simplify for the sake of it
26- You don't understand what the code does yet — comprehend before you simplify
27- The code is performance-critical and the "simpler" version would be measurably slower
28- You're about to rewrite the module entirely — simplifying throwaway code wastes effort
29
30## The Five Principles
31
32### 1. Preserve Behavior Exactly
33
34Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it.
35
36```
37ASK BEFORE EVERY CHANGE:
38→ Does this produce the same output for every input?
39→ Does this maintain the same error behavior?
40→ Does this preserve the same side effects and ordering?
41→ Do all existing tests still pass without modification?
42```
43
44### 2. Follow Project Conventions
45
46Simplification means making code more consistent with the codebase, not imposing external preferences. Before simplifying:
47
48```
491. Read CLAUDE.md / project conventions
502. Study how neighboring code handles similar patterns
513. Match the project's style for:
52 - Import ordering and module system
53 - Function declaration style
54 - Naming conventions
55 - Error handling patterns
56 - Type annotation depth
57```
58
59Simplification that breaks project consistency is not simplification — it's churn.
60
61### 3. Prefer Clarity Over Cleverness
62
63Explicit code is better than compact code when the compact version requires a mental pause to parse.
64
65```typescript
66// UNCLEAR: Dense ternary chain
67const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';
68
69// CLEAR: Readable mapping
70function getStatusLabel(item: Item): string {
71 if (item.isNew) return 'New';
72 if (item.isUpdated) return 'Updated';
73 if (item.isArchived) return 'Archived';
74 return 'Active';
75}
76```
77
78```typescript
79// UNCLEAR: Chained reduces with inline logic
80const result = items.reduce((acc, item) => ({
81 ...acc,
82 [item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 }
83}), {});
84
85// CLEAR: Named intermediate step
86const countById = new Map<string, number>();
87for (const item of items) {
88 countById.set(item.id, (countById.get(item.id) ?? 0) + 1);
89}
90```
91
92### 4. Maintain Balance
93
94Simplification has a failure mode: over-simplification. Watch for these traps:
95
96- **Inlining too aggressively** — removing a helper that gave a concept a name makes the call site harder to read
97- **Combining unrelated logic** — two simple functions merged into one complex function is not simpler
98- **Removing "unnecessary" abstraction** — some abstractions exist for extensibility or testability, not complexity
99- **Optimizing for line count** — fewer lines is not the goal; easier comprehension is
100
101### 5. Scope to What Changed
102
103Default to simplifying recently modified code. Avoid drive-by refactors of unrelated code unless explicitly asked to broaden scope. Unscoped simplification creates noise in diffs and risks unintended regressions.
104
105## The Simplification Process
106
107### Step 1: Understand Before Touching (Chesterton's Fence)
108
109Before changing or removing anything, understand why it exists. This is Chesterton's Fence: if you see a fence across a road and don't understand why it's there, don't tear it down. First understand the reason, then decide if the reason still applies.
110
111```
112BEFORE SIMPLIFYING, ANSWER:
113- What is this code's responsibility?
114- What calls it? What does it call?
115- What are the edge cases and error paths?
116- Are there tests that define the expected behavior?
117- Why might it have been written this way? (Performance? Platform constraint? Historical reason?)
118- Check git blame: what was the original context for this code?
119```
120
121If you can't answer these, you're not ready to simplify. Read more context first.
122
123### Step 2: Identify Simplification Opportunities
124
125Scan for these patterns — each one is a concrete signal, not a vague smell:
126
127**Structural complexity:**
128
129| Pattern | Signal | Simplification |
130|---------|--------|----------------|
131| Deep nesting (3+ levels) | Hard to follow control flow | Extract conditions into guard clauses or helper functions |
132| Long functions (50+ lines) | Multiple responsibilities | Split into focused functions with descriptive names |
133| Nested ternaries | Requires mental stack to parse | Replace with if/else chains, switch, or lookup objects |
134| Boolean parameter flags | doThing(true, false, true) | Replace with options objects or separate functions |
135| Repeated conditionals | Same if check in multiple places | Extract to a well-named predicate function |
136
137**Naming and readability:**
138
139| Pattern | Signal | Simplification |
140|---------|--------|----------------|
141| Generic names | data, result, temp, val, item | Rename to describe the content: userProfile, validationErrors |
142| Abbreviated names | usr, cfg, btn, evt | Use full words unless the abbreviation is universal (id, url, api) |
143| Misleading names | Function named get that also mutates state | Rename to reflect actual behavior |
144| Comments explaining "what" | // increment counter above count++ | Delete the comment — the code is clear enough |
145| Comments explaining "why" | // Retry because the API is flaky under load | Keep these — they carry intent the code can't express |
146
147**Redundancy:**
148
149| Pattern | Signal | Simplification |
150|---------|--------|----------------|
151| Duplicated logic | Same 5+ lines in multiple places | Extract to a shared function |
152| Dead code | Unreachable branches, unused variables, commented-out blocks | Remove (after confirming it's truly dead) |
153| Unnecessary abstractions | Wrapper that adds no value | Inline the wrapper, call the underlying function directly |
154| Over-engineered patterns | Factory-for-a-factory, strategy-with-one-strategy | Replace with the simple direct approach |
155| Redundant type assertions | Casting to a type that's already inferred | Remove the assertion |
156
157### Step 3: Apply Changes Incrementally
158
159Make one simplification at a time. Run tests after each change. **Submit refactoring changes separately from feature or bug fix changes.** A PR that refactors and adds a feature is two PRs — split them.
160
161```
162FOR EACH SIMPLIFICATION:
1631. Make the change
1642. Run the test suite
1653. If tests pass → commit (or continue to next simplification)
1664. If tests fail → revert and reconsider
167```
168
169Avoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it.
170
171**The Rule of 500:** If a refactoring would touch more than 500 lines, invest in automation (codemods, sed scripts, AST transforms) rather than making the changes by hand. Manual edits at that scale are error-prone and exhausting to review.
172
173### Step 4: Verify the Result
174
175After all simplifications, step back and evaluate the whole:
176
177```
178COMPARE BEFORE AND AFTER:
179- Is the simplified version genuinely easier to understand?
180- Did you introduce any new patterns inconsistent with the codebase?
181- Is the diff clean and reviewable?
182- Would a teammate approve this change?
183```
184
185If the "simplified" version is harder to understand or review, revert. Not every simplification attempt succeeds.
186
187## Language-Specific Guidance
188
189### TypeScript / JavaScript
190
191```typescript
192// SIMPLIFY: Unnecessary async wrapper
193// Before
194async function getUser(id: string): Promise<User> {
195 return await userService.findById(id);
196}
197// After
198function getUser(id: string): Promise<User> {
199 return userService.findById(id);
200}
201
202// SIMPLIFY: Verbose conditional assignment
203// Before
204let displayName: string;
205if (user.nickname) {
206 displayName = user.nickname;
207} else {
208 displayName = user.fullName;
209}
210// After
211const displayName = user.nickname || user.fullName;
212
213// SIMPLIFY: Manual array building
214// Before
215const activeUsers: User[] = [];
216for (const user of users) {
217 if (user.isActive) {
218 activeUsers.push(user);
219 }
220}
221// After
222const activeUsers = users.filter((user) => user.isActive);
223
224// SIMPLIFY: Redundant boolean return
225// Before
226function isValid(input: string): boolean {
227 if (input.length > 0 && input.length < 100) {
228 return true;
229 }
230 return false;
231}
232// After
233function isValid(input: string): boolean {
234 return input.length > 0 && input.length < 100;
235}
236```
237
238### Python
239
240```python
241# SIMPLIFY: Verbose dictionary building
242# Before
243result = {}
244for item in items:
245 result[item.id] = item.name
246# After
247result = {item.id: item.name for item in items}
248
249# SIMPLIFY: Nested conditionals with early return
250# Before
251def process(data):
252 if data is not None:
253 if data.is_valid():
254 if data.has_permission():
255 return do_work(data)
256 else:
257 raise PermissionError("No permission")
258 else:
259 raise ValueError("Invalid data")
260 else:
261 raise TypeError("Data is None")
262# After
263def process(data):
264 if data is None:
265 raise TypeError("Data is None")
266 if not data.is_valid():
267 raise ValueError("Invalid data")
268 if not data.has_permission():
269 raise PermissionError("No permission")
270 return do_work(data)
271```
272
273### React / JSX
274
275```tsx
276// SIMPLIFY: Verbose conditional rendering
277// Before
278function UserBadge({ user }: Props) {
279 if (user.isAdmin) {
280 return <Badge variant="admin">Admin</Badge>;
281 } else {
282 return <Badge variant="default">User</Badge>;
283 }
284}
285// After
286function UserBadge({ user }: Props) {
287 const variant = user.isAdmin ? 'admin' : 'default';
288 const label = user.isAdmin ? 'Admin' : 'User';
289 return <Badge variant={variant}>{label}</Badge>;
290}
291
292// SIMPLIFY: Prop drilling through intermediate components
293// Before — consider whether context or composition solves this better.
294// This is a judgment call — flag it, don't auto-refactor.
295```
296
297## Common Rationalizations
298
299| Rationalization | Reality |
300|---|---|
301| "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change. |
302| "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. |
303| "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused. |
304| "The types make it self-documenting" | Types document structure, not intent. A well-named function explains *why* better than a type signature explains *what*. |
305| "This abstraction might be useful later" | Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed. |
306| "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure. |
307| "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. |
308
309## Red Flags
310
311- Simplification that requires modifying tests to pass (you likely changed behavior)
312- "Simplified" code that is longer and harder to follow than the original
313- Renaming things to match your preferences rather than project conventions
314- Removing error handling because "it makes the code cleaner"
315- Simplifying code you don't fully understand
316- Batching many simplifications into one large, hard-to-review commit
317- Refactoring code outside the scope of the current task without being asked
318
319## Verification
320
321After completing a simplification pass:
322
323- [ ] All existing tests pass without modification
324- [ ] Build succeeds with no new warnings
325- [ ] Linter/formatter passes (no style regressions)
326- [ ] Each simplification is a reviewable, incremental change
327- [ ] The diff is clean — no unrelated changes mixed in
328- [ ] Simplified code follows project conventions (checked against CLAUDE.md or equivalent)
329- [ ] No error handling was removed or weakened
330- [ ] No dead code was left behind (unused imports, unreachable branches)
331- [ ] A teammate or review agent would approve the change as a net improvement
332
In the file
SKILL.md2,028 words
Files1
LicenceMIT
Why you can read it

Nothing in a skill executes. The client loads the text and the model follows it, so a skill can be audited the way a runbook is — by reading it.

What it costs in context

Skills are not billed by the call. They are paid for in context: every token the instructions occupy is a token your code, your diff and your conversation cannot use. Here is what this one takes and when it takes it.

≈70
always loaded
The name and description, so the model knows the skill exists and when to reach for it.
3,305
on trigger
The instruction body, read only when the skill fires.
1.7%
of a 200k window
Ten skills this size would take about 17% of the window before you open a file.
050k100k150k200k context window

3.4k tokens, estimated from the bundle at four bytes to the token, held for the rest of the session once it triggers. Middling. Fine to keep on in a project where you use it weekly, worth unloading in one where you never do.

Servers bill, skills cost

A server charges by the month. A skill charges once per session, in context, and then keeps charging it for as long as the session lives.

Before and after

The same question, put to the same model twice: once as it comes, and once with these instructions loaded.

No worked example has been published for this skill yet.

Adoption
Installsnone yet
Ratingno reviews yet

The procedure it runs

The procedure has not been published here. It is in the skill’s own SKILL.md, which its author has not sent to the marketplace yet.

Prose, not code

These steps are written for a model to follow, not executed by a runtime. It can still be told to skip one, and it will say so when it does.

Servers it uses

None. This skill calls no MCP servers at all.

Everything it needs is in the instructions, so it works in a project with nothing connected — the model reads the file and changes how it works with what it can already reach.

It writes no files and reaches no network. All it changes is how the model reasons and writes.

What it asks for
Writes filesno
Network accessno

Read from the allowed-tools line of this skill’s own SKILL.md. A skill grants no permissions of its own — it can only ask for tools your client already has.

What it will not do

Every skill is narrow, and the useful ones say where they stop. These are the jobs this one is the wrong tool for.

What this skill is not for has not been published here. Nothing is implied by that: it is a section the author has not filled in.

What is in the bundle

1 file, 13.5 kB on disk. A bundle is text throughout: the instructions the model reads, plus the templates it fills in.

  • SKILL.md13.5 kB
What is not in it

No dependencies and nothing executable: a skill is text the agent reads, so the bundle is 1 file you can review in full before installing. The MIT licence covers the templates and examples as well as the instructions.

Install

Installing copies the bundle into your project. Nothing runs at install time — the files sit on disk until the model reads them.

# Code Simplification · 3.4k tokens when loaded npx mcprush@latest skill add addyosmani/code-simplification

Writes to .claude/skills/code-simplification/ in the current project. Add --global to put it in your home directory instead, for every project.

Which clients pick it up on their own

A skill is a folder of text. A client with a skills folder reads it without being told; everywhere else the same text works, it is just handed to the model rather than found.

Claude Code.claude/skills/
Claude Desktop
ChatGPT
Cursor.cursor/skills/
VS Code.github/skills/
Codex CLI.agents/skills/
Gemini CLI.gemini/skills/
Grok.grok/skills/
Zed.agents/skills/
Windsurf.windsurf/skills/
Agent SDK.claude/skills/
HTTP / API
This release
Versionnot versioned
Publishedno release date on file
PriceFree
Referenceaddyosmani/code-simplification

Versions

Its author publishes no version number, so there is nothing here to pin to: what you install is the folder as it stands today. Instructions change more often than APIs do — a skill can be rewritten entirely without anything it depends on moving.

v
  • No earlier releases have been published to the marketplace.
Pinning

Nothing to pin to: this skill carries no version number of its own. What you install is what the folder holds on the day you install it.

Reviews

no reviews yet · no installs yet

Nobody has reviewed this skill yet. The rating is the mean of the reviews written here, so there is none until somebody writes the first.

Who can post

Only accounts that have had the skill installed for fourteen days, so a review is written after living with it rather than after reading it. Publishers may reply once.

Publisher
Servers0