/clean-code
Use when writing or reviewing functions, classes, naming, or non-trivial logic (≥3 lines)
$ npx -y skills add oribarilan/97 --skill clean-code --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/clean-code
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when writing or reviewing functions, classes, naming, or non-trivial logic (≥3 lines)
SKILL.md
clean-code.SKILL.mdname: clean-code
description: Use when writing or reviewing functions, classes, naming, or non-trivial logic (≥3 lines)
Writing Clean Code
Overview
**Code is read far more often than it is written, so optimize the artifact for the next reader.** This skill is a small set of decisions to apply when you write a new function, name a new entity, or touch a non-trivial block of logic. Each decision pairs with a check a reviewer (human or agent) could apply by reading the diff.
When to invoke
Invoke when you're about to:
- Add a new function, method, class, struct, or module
- Name a new entity that other code will reference (variable, function, type, file)
- Modify ≥3 lines of non-trivial logic — branching, loops, conditional dispatch, or anything that reads as "behavior" rather than "wiring"
- Add or replace a comment block of more than one line
- Copy-paste a block of logic from elsewhere in the codebase
- Review code for readability, naming, duplication, or structural quality
If you're unsure whether the change is non-trivial, ask: *would a reviewer pause on this hunk to think about it?* If yes, invoke.
Non-triggers — do NOT invoke for
- Typo fixes or one-line bug fixes where the change is obvious
- Config edits — JSON, YAML, TOML, dotfiles, lock files, env files
- Test code (use `testing-discipline` instead)
- Refactoring existing code (use `before-you-refactor` instead)
- Mechanical edits — running a formatter, sorting imports, renaming a single local variable in one function
- Generated code
The clean-code decisions
Each decision pairs with a **check** — a property a reviewer can verify by reading the diff.
1. **Reach simplicity by removing, not adding.** (KISS) *(Homer, 97/75.)* The reflex when code misbehaves is to add another variable, branch, or comment. Try the opposite — delete a line and see what breaks. Bad code that is close to working is worth saving; bad code that is far from working should be discarded and retyped from memory. *Check:* you tried deleting at least one line you initially wrote on this hunk, and the code is better for what survived.
2. **Reason about each block in short sections.** *(Kimchi, 97/15.)* Write code in chunks — a single line up to under ten — that you could defend to a sceptical peer. The endpoints of each section should be describable as state properties (a generalized pre/postcondition or invariant). When you intend to reason about the code, the structure improves on its own: smaller scopes, fewer mutable globals, narrower interfaces, getters that don't leak internal state. *Check:* you can describe, in one sentence, what state holds at the start and end of each block of ten or fewer lines.
3. **Find examples in domain terms before writing the function.** *(Braithwaite, 97/94.)* A function with an `int` parameter has billions of input cases; a function with a `LibertyCount = {1,2,3,4}` parameter has four. Pick the types that make the function checkable by example, then write it. *Check:* every parameter that could be a domain type is one (or there's a named reason it's not — measured perf, language limitation, deferred to a tracked issue).
4. **One reason to change per unit.** *(Martin, 97/76.)* The Single Responsibility Principle (SRP): a function, class, or module should have one reason to change. An `Employee` class with `calculatePay`, `reportHours`, and `save` has three reasons to change and three sets of dependents who suffer for each. Split along axes of change, not axes of "things that share a noun." See `before-you-refactor` for when to *trigger* a split on existing code. *Check:* the responsibility of each function/class/module fits in one sentence with no "and also."
5. **Treat layout as a tool for the reader, not for the parser.** *(Freeman, 97/13.)* Standardize accidental complexity (formatter handles the basics) so domain content stands out. Use line breaks to express intention. Compact, scannable code beats sparse ceremonial code on every metric the reader cares about. *Check:* removing any blank line in the hunk would either obscure intent or prove it wasn't doing work.
6. **Names match the domain; no name relies on local context.** *(Sommerlad, 97/62 — distilled.)* Context evaporates the moment the reader is somewhere else in the file. Names carry their meaning with them. *Check:* every new name reads correctly when the reviewer encounters it for the first time, with the surrounding lines hidden.
7. **Comment only what the code cannot say.** *(Henney, 97/17.)* A comment that restates what the code does adds nothing. A comment that contradicts the code is worse than nothing — wrong comments survive forever because no compiler catches them. The legitimate space is *why this approach, not what it does*. *Check:* every comment in the hunk explains *why*, not *what*; comments that describe the code itself are deleted, and the underlying name or extraction is improved instead.
8. **Each piece of knowledge has one authoritative representation.** *(Smith, 97/30; performance-angle credit Pepperdine, 97/91.)* DRY applies to data, logic, and process. Copy-paste duplication is the easy case to spot; the harder case is parallel implementations of the same business rule that drift apart over time. (Bonus from 97/91: a hot path concentrated in one place shows up clearly in a profile; spread across copies, each looks like noise.) Occasional duplication for a measured performance reason is fine; speculative duplication is not. *Check:* no business rule is implemented in two places without a named reason; if it is, the reason is recorded inline or in the commit message.
Long-term mindset vs YAGNI — the tension
"Write for long-term support" and "remove anything you don't need" sound contradictory and aren't. **Long-term thinking is about clarity, not predictive feature engineering.** Invest in good names, small functions, honest comments, removed dead code, tests that pin behavi
Read more
name: clean-code description: Use when writing or reviewing functions, classes, naming, or non-trivial logic (≥3 lines)
Writing Clean Code
Overview
**Code is read far more often than it is written, so optimize the artifact for the next reader.** This skill is a small set of decisions to apply when you write a new function, name a new entity, or touch a non-trivial block of logic. Each decision pairs with a check a reviewer (human or agent) could apply by reading the diff.
When to invoke
Invoke when you're about to:
- Add a new function, method, class, struct, or module
- Name a new entity that other code will reference (variable, function, type, file)
- Modify ≥3 lines of non-trivial logic — branching, loops, conditional dispatch, or anything that reads as "behavior" rather than "wiring"
- Add or replace a comment block of more than one line
- Copy-paste a block of logic from elsewhere in the codebase
- Review code for readability, naming, duplication, or structural quality
If you're unsure whether the change is non-trivial, ask: *would a reviewer pause on this hunk to think about it?* If yes, invoke.
Non-triggers — do NOT invoke for
- Typo fixes or one-line bug fixes where the change is obvious
- Config edits — JSON, YAML, TOML, dotfiles, lock files, env files
- Test code (use `testing-discipline` instead)
- Refactoring existing code (use `before-you-refactor` instead)
- Mechanical edits — running a formatter, sorting imports, renaming a single local variable in one function
- Generated code
The clean-code decisions
Each decision pairs with a **check** — a property a reviewer can verify by reading the diff.
1. **Reach simplicity by removing, not adding.** (KISS) *(Homer, 97/75.)* The reflex when code misbehaves is to add another variable, branch, or comment. Try the opposite — delete a line and see what breaks. Bad code that is close to working is worth saving; bad code that is far from working should be discarded and retyped from memory. *Check:* you tried deleting at least one line you initially wrote on this hunk, and the code is better for what survived.
2. **Reason about each block in short sections.** *(Kimchi, 97/15.)* Write code in chunks — a single line up to under ten — that you could defend to a sceptical peer. The endpoints of each section should be describable as state properties (a generalized pre/postcondition or invariant). When you intend to reason about the code, the structure improves on its own: smaller scopes, fewer mutable globals, narrower interfaces, getters that don't leak internal state. *Check:* you can describe, in one sentence, what state holds at the start and end of each block of ten or fewer lines.
3. **Find examples in domain terms before writing the function.** *(Braithwaite, 97/94.)* A function with an `int` parameter has billions of input cases; a function with a `LibertyCount = {1,2,3,4}` parameter has four. Pick the types that make the function checkable by example, then write it. *Check:* every parameter that could be a domain type is one (or there's a named reason it's not — measured perf, language limitation, deferred to a tracked issue).
4. **One reason to change per unit.** *(Martin, 97/76.)* The Single Responsibility Principle (SRP): a function, class, or module should have one reason to change. An `Employee` class with `calculatePay`, `reportHours`, and `save` has three reasons to change and three sets of dependents who suffer for each. Split along axes of change, not axes of "things that share a noun." See `before-you-refactor` for when to *trigger* a split on existing code. *Check:* the responsibility of each function/class/module fits in one sentence with no "and also."
5. **Treat layout as a tool for the reader, not for the parser.** *(Freeman, 97/13.)* Standardize accidental complexity (formatter handles the basics) so domain content stands out. Use line breaks to express intention. Compact, scannable code beats sparse ceremonial code on every metric the reader cares about. *Check:* removing any blank line in the hunk would either obscure intent or prove it wasn't doing work.
6. **Names match the domain; no name relies on local context.** *(Sommerlad, 97/62 — distilled.)* Context evaporates the moment the reader is somewhere else in the file. Names carry their meaning with them. *Check:* every new name reads correctly when the reviewer encounters it for the first time, with the surrounding lines hidden.
7. **Comment only what the code cannot say.** *(Henney, 97/17.)* A comment that restates what the code does adds nothing. A comment that contradicts the code is worse than nothing — wrong comments survive forever because no compiler catches them. The legitimate space is *why this approach, not what it does*. *Check:* every comment in the hunk explains *why*, not *what*; comments that describe the code itself are deleted, and the underlying name or extraction is improved instead.
8. **Each piece of knowledge has one authoritative representation.** *(Smith, 97/30; performance-angle credit Pepperdine, 97/91.)* DRY applies to data, logic, and process. Copy-paste duplication is the easy case to spot; the harder case is parallel implementations of the same business rule that drift apart over time. (Bonus from 97/91: a hot path concentrated in one place shows up clearly in a profile; spread across copies, each looks like noise.) Occasional duplication for a measured performance reason is fine; speculative duplication is not. *Check:* no business rule is implemented in two places without a named reason; if it is, the reason is recorded inline or in the commit message.
Long-term mindset vs YAGNI — the tension
"Write for long-term support" and "remove anything you don't need" sound contradictory and aren't. **Long-term thinking is about clarity, not predictive feature engineering.** Invest in good names, small functions, honest comments, removed dead code, tests that pin behavi
Showing the first part of this file.
Agent skills distilled from the hard-won lessons of world-renowned programmers, in the spirit of "97 Things Every Programmer Should Know"
Repo: oribarilan/97
Other skills on 97.
- /api-design
Use when designing or reviewing a public API, exported function signature, module boundary, exported type/interface, or any contract other code depends on
Open skill - /before-you-refactor
Use when considering, evaluating, or performing a refactor, restructure, cross-file rename, or cleanup
Open skill - /build-deploy-and-tooling
Use when writing, reviewing, or changing build scripts, CI workflows, deploy pipelines, repo setup, or evaluating a new tool/dependency
Open skill - /correctness-traps
Use when writing or reviewing error handling, floating-point math, concurrent code, remote calls, singletons/globals, hot-path data structures, or high-volume log statements
Open skill - /domain-modeling
Use when introducing, reviewing, or renaming a top-level type, table, or domain concept; or choosing where state lives (in-memory vs persistent)
Open skill - /observability
Use when writing or reviewing request handlers, RPCs, or background jobs for production; adding tracing, metrics, or structured-log calls; or making diagnosability decisions
Open skill

