clean-code
Skill1 starsChanged 2 months agoMITView on GitHub
Senior-engineer discipline for writing and changing code without AI slop. Use when writing, editing, refactoring, or structuring code in any language, and when the user mentions clean code, slop, over-engineering, tech debt, dead code, simplifying, security, or project structure.
108 other projects use a version of this.
Adopted by
Most recently taken up by
- sbluemin/fleet-harnesstheir own version, first seen Nov 8, 2026
- nohemi20231/design-skillstheir own version, first seen Nov 8, 2026
- Mahesh-Bishnoi/skillstheir own version, first seen Nov 8, 2026
- Bruno-Cunha-Souza/ValarMindSkillstheir own version, first seen Nov 8, 2026
- kana-consultant/kana-best-practice-engineeringtheir own version, first seen Nov 8, 2026
- uwuclxdy/agenticattheir own version, first seen Nov 8, 2026
Used with
Projects with it also use intelligent-routing, nextjs-react-expert and 9 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
SKB3002Skillintelligent-routing
Automatic agent selection and intelligent task routing. Analyzes user requests and automatically selects the best specialist agent(s) without requiring explicit user mentions.
Also in 5 projects that use this
SKB3002Skillnextjs-react-expert
React and Next.js performance optimization from Vercel Engineering. Use when building React components, optimizing performance, eliminating waterfalls, reducing bundle size, reviewing code for performance issues, or implementing server/client-side optimizations.
Also in 3 projects that use this
xfstudioSkillbash-pro
Master of defensive Bash scripting for production automation, CI/CD
Also in 4 projects that use this
xfstudioSkillcode-refactoring-tech-debt
You are a technical debt expert specializing in identifying, quantifying, and prioritizing technical debt in software projects. Analyze the codebase to uncover debt, assess its impact, and create acti
Also in 4 projects that use this
goca-seSkillbatch-operations
Apply a change safely across many files — refactors touching more than 5 files, library or API migrations, project-wide renames of symbols/imports/paths, or adding boilerplate to many files. Use when "do it all at once" risks context overflow or silent failures.
Also in 3 projects that use this
nek1987Skillsolid-principles
SOLID object-oriented design principles for maintainable code
Also in 4 projects that use this
- +4 more from xfstudio
Other versions108 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 108
- superplanehq/superplane★ 9.1ksame name
- vudovn/ag-kit★ 8.2ksame name
- vudovn/antigravity-kit★ 8.2ksame name
- Openpanel-dev/openpanel★ 7.3ksame name
- ciembor/agent-rules-books★ 2.8ksame name
- wondelai/skills★ 2.6ksame name
- decebals/claude-code-java★ 763same name
- operately/operately★ 618same name
- liza-mas/liza★ 418same name
- Mindrally/skills★ 275same name
98 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository7 other files it gives its agents.
- auditSkill
- clean-code-reviewSkill
- clean-code-setupSkill
- deslopSkill
- finishSkill
- interrogateSkill
- test-auditSkill
The file
We split this skill into the rules it gives an agent
1 rule. 0 are common, 1 is distinctive, and 0 are very specific to this project.
0
Common
Most of the 101 edited versions we read keep these.
1
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 40
Only what the gates do not already say.
“Common” is measured: kept by at least 6 in 10 of the 101 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Clean Code
Write code a senior engineer would merge without comment. The enemy is slop: code that works, passes a glance, and still degrades the codebase (narration comments, dead branches, one-call helpers, defensive paranoia, copy-pasted blocks, abstractions for futures that never arrive, tests that cannot fail). Slop is complexity added at machine speed.
Three ideas govern everything below. Every line earns its place: a line stays when deleting it would lose behaviour or information. Match the codebase, then these defaults: mirror the surrounding comment density, naming, idiom, and structure; a repo's CODING_STANDARDS.md (or CONTRIBUTING.md, CLAUDE.md, AGENTS.md) overrides this skill. Evidence over confidence: the burden of proof is on the author; a change ships with the command that proves it, the test that went red before it, and a plain statement of what was not verified.
The loop
Sized to the change: seconds for a one-line fix, deliberate for a feature.
- Understand. Read the code and its callers; reuse the existing pattern. Name the seam (the interface the change lives behind) and the check that proves it. For a library outside the standard library, read its current docs or types; recalled APIs go stale. When two readings of the request lead to different code, present both with a recommendation and ask. Done when one sentence says what changes, where, and how it is verified.
- Shape. The smallest change that fully solves the request, behind the smallest interface that hides it. Sketch a second, radically different shape for any non-trivial interface. Naive and obviously correct first; optimize only against a measurement.
- Write. Apply the gates and rules below.
- Verify. Typecheck, focused tests, lint, then the full suite once. Close the loop with real execution where it applies (the program, the request, the browser). Read the output. "Tests pass" means they ran in this session with zero failures.
- Interrogate. What is unnecessary, over-complicated, or resting on a weak assumption? What can be deleted entirely, and what simplifies once it is gone? Prefer deleting over simplifying, simplifying over optimizing, optimizing over automating. Make the cuts; if it is already right, leave it alone.
- Report. End with the block in Report.
Hard gates
A change that fails one of these is not done. These eight rows are the checklist; there is no second list.
| Gate | Standard |
| Surgical | Every changed line traces to the request. Adjacent code, comments, and formatting stay as they were; a comment that is not understood is left alone. Orphans the change created (imports, variables, functions, files) are removed. Pre-existing dead code is reported, not touched. |
| Zero dead code | No unused symbols, unreachable branches, commented-out code, stubs, placeholders, or scaffolding for later. Removal is complete: no shims, re-exports, or _legacy aliases unless asked. On a published surface (package exports, an API, a CLI flag), "unused" must include consumers outside the repo; that removal is a decision, not a cleanup. |
| Comments carry information | A comment stays only when it says what the code cannot: why, an invariant, a constraint, a consequence, a link to the decision. Narration, restatement, banners, step numbers, and end markers go. The why that does not fit a comment goes in the commit body. |
| Structure follows need | An abstraction earns its place by hiding a decision, naming a concept, or isolating what varies. A one-caller helper that hides nothing is inlined; one that names a calculation may stay. An interface with one implementation is a hypothetical seam unless a second adapter exists or is named in writing (a test fake, a vendor boundary). No forwarding wrapper, no option nobody sets, no config for what does not vary, no copy of a helper that exists elsewhere. |
| Boundaries validate, internals trust | Parse untrusted input once at the edge (user input, network, files, external APIs) into a named type; inside, trust the types and invariants. Errors surface: a catch that swallows, a fallback that hides a failure, or a null check on a guaranteed value is a bug. |
| Safe by default | Queries parameterized; shell, path, URL, and HTML sinks never receive raw strings. Authorization checked at every entry point for the object, not just the session. Secrets from configuration. Every external call has a timeout; retries only where the operation is idempotent, and then bounded. Multi-step writes atomic or idempotent. No secrets or personal data in logs. Failure closes, never opens. Catalog with evidence and fixes: BUGS.md. |
| Tests can fail | Every test protects a behaviour a caller depends on, at the public seam, and was seen red once. It asserts an outcome; an interaction only when the interaction is the contract at an external boundary (a charge captured once, an event published). No tests of framework behaviour, private internals, or duplicates; a test of trivial code stays only when that value is a contract callers depend on. Expected values come from an independent source, never recomputed the way the code computes them. Mock only boundaries the project does not own; inject a dependency instead of mocking an own module. |
| Evidence before done | The verification command ran in this session, its output was read, and it passed. Green was never reached by weakening the check: a test rewritten to match new behaviour, a skip, a lowered threshold, a suppression, or a stub is a finding, not a fix. A test changed on purpose carries the reason in the commit; a test deleted names the coverage that remains. |
Writing rules
Only what the gates do not already say. Detail and examples live one link away.
- Simplicity. If 200 lines could be 50, rewrite. One thing per line: a named intermediate beats a call chained into an index into a ternary. Three similar lines beat a premature abstraction; copy-pasted blocks with cosmetic variation are worse than both. A function over a class, a value over a flag, a table over a recurring switch, a guard clause over nesting. Happy path unindented; special cases handled early or designed out of existence. A refactor that moves code without reducing what a reader must hold in their head is not an improvement.
- The better shape. Inside the lines being touched, leave the design as it would be had the change been known from the start; when the code is the wrong shape and a clearly better one exists (smaller interface, a special case gone, one piece of knowledge in one place) and the seam tests pass unchanged, write the better shape. Outside those lines, report and leave it. Deep modules, layout, dependency direction, safe moves: STRUCTURE.md.
- The day it goes wrong. Dependencies as parameters; results returned, inputs not mutated; pure core, effects at the edge. Total operations where the domain allows, illegal states unrepresentable where it does not. One owner per resource, closed on the error path. A check followed by an act on shared state is a race until it is atomic. Work bounded to the input: paginate, stream, batch; a query inside a loop is a finding.
- Naming. Precise and consistent, one term per concept, length scaling with scope. Booleans as predicates, functions as verbs, types as nouns; no redundant qualifiers. A hard-to-pick name means two concepts. Use the project's domain vocabulary.
- Errors. Define the error out of existence first; handle each once, at the level that can act on it; fail loudly on the impossible and closed on the sensitive; messages name what failed, what was expected, and the values. Idiom per language: ERRORS.md.
- Comments. The file's density. Precision (units, boundaries, ownership) or intuition (the sentence that explains a block); never what a first-time reader could write from the code. Docstrings state the contract.
TODOcarries an owner or ticket. COMMENTS.md. - Tests. Level by the seam where the behaviour is observable, not by habit; one behaviour per test, named as a capability, self-contained; red before green; the repo's real test command from
package.json, theMakefile, or CI. TESTS.md. - Types as evidence. Parse once at the boundary;
typeofnarrowing inside, orunknown,any,object,Record<string, unknown>in internal signatures, means the evidence was thrown away. Never launder a type; a necessary assertion carries aSAFETY:comment naming the invariant. Unions over boolean pairs, distinct ID types where mix-ups are plausible, suppressions only with a reason. - Instruction files.
CLAUDE.md,AGENTS.md,README.md, and memory files fill with implementation details, session observations, and stale docs. Write only what the code cannot say, delete what went stale in the same edit, and enforce a must-hold rule with a test, a lint rule, or a hook instead of prose. When the user corrects a pattern, offer one dated line forCODING_STANDARDS.md; the review enforces it from then on.
Complexity budget
Numbers a linter can enforce; crossing one means restructure along responsibilities, not extract a meaningless helper. /clean-code-setup wires them into the linter; scripts/complexity.sh [path] prints every function's complexity, the hotspots, and erosion (the share of complexity in functions over budget).
| Measure | Limit |
| Cyclomatic complexity per function | 10 |
| Nesting depth | 3 |
| Parameters | 4, the rest in a typed object |
| Function length | 50 lines is a smell to examine, not a limit |
| File length | 400 lines is a signal to split by responsibility |
Report
Close every piece of work with this block. Numbers from scripts/diff-stats.sh [base] and scripts/complexity.sh [path] (repo root; git and bash) and from the commands that actually ran. A gate that did not run says n/a, never pass.
## Clean Code Report
Scope <request in one line> · <N files>
Diff +<added> / -<removed> lines · net <±n>
Removed dead code <n> · comments <n> · debug statements <n> · abstractions <n>
Gates typecheck <pass|fail|n/a> · lint <pass|fail|n/a> · tests <passed>/<total>
Complexity max <n> · over budget <n> · erosion <x%> (or n/a)
Unverified <what could not be run, and why, or "nothing">
Left <things noticed outside scope, or "nothing">
Verdict <ready | needs decision: ...>Reference
Load the section the task needs, not the file: grep -n '^##' <file> shows the map. RED-FLAGS.md: slop tells, Ousterhout's red flags, Fowler's smells, each with its fix. BUGS.md: correctness, robustness, and security tells with the evidence each needs. Companion skills: /finish before a commit; /deslop and /deslop repo for existing code; /audit, /test-audit, /interrogate, /clean-code-review for the pieces; /clean-code-setup for the gates and hooks.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

