Repository navigation
clean-code.zip below is the skill for Claude Desktop / claude.ai upload. In a project, re-run the installer (scripts/install.sh or scripts/install.ps1) to update the skill and the managed block.
Full entry from CHANGELOG.md:
Stack-aware release. The skill now carries a short, strict pack for each of 21 languages and 27
frameworks, loads only the packs a project needs, and maps every file's functions and classes to
show misplaced, mixed, duplicated, badly named, and badly organized code in one place. The core
shrank, and was then rewritten terser still, so the context an agent must read before its first
edit stays small on any model.
Breaking
- Layer rules are framework-first. The skill follows each framework's own idiomatic structure,
and the strict Clean Architecture layer rules apply only when.clean/architecture.mddeclares
layers. Projects that relied on layers being assumed should declare them;/clean-code init
asks, and proposes an ordering from the detected layer candidates. questionsis nowinit.references/questions.mdbecamereferences/init.md; the
questionscommand still works as an alias.initdetects the stack, runs the interview, maps
the structure, and writes.clean/.- The managed block changed: placement is role-based and the layer section is framework-first.
Re-run the installer to update it.
Added
- Language and framework packs under
references/languages/andreferences/frameworks/:
TypeScript, JavaScript, Python, Java, C, C++, C#, PHP, Go, Rust, Swift, Objective-C, Kotlin, Ruby,
Shell, PowerShell, R, Dart, Scala, CSS, Sass; React, Next.js, Vue and Nuxt, Angular, Svelte and
SvelteKit, Tailwind CSS, Django, Flask, FastAPI, Express, NestJS, Strapi, Spring, ASP.NET Core
with EF Core, Laravel, Symfony, Drupal, WordPress, Ruby on Rails, Gin and Beego, Ktor, Jetpack
Compose, SwiftUI and UIKit, Flutter, Unity, TensorFlow, PyTorch. Language packs cover names,
functions and types, errors, modules, placement, tests, layers, enforcement, and smells; framework
packs cover structure, roles, rules, layers, tests, enforcement, and smells; every pack's Names
section now names its stack's concrete naming anti-patterns. Each stays under 2,000 tokens.
Detection covers Tailwind CSS (tailwindcssinpackage.json), Drupal (drupal/corein
composer.json), WordPress (wp-config.php,wp-content/, or WordPress core in
composer.json), and Unity (ProjectSettings/ProjectVersion.txtorcom.unity.packages); the
project walker skips each framework's generated folders (Unity'sLibrary/,Temp/,Logs/,
UserSettings/; Drupal'score/,contrib/; WordPress'swp-admin/,wp-includes/; Flutter's
ephemeral build output). Laravel's pack states each major version's support status, re-verified
against current documentation. - Pack routing.
framework-map.mdholds the pack index;detect_stack.pyrecords the selected
packs incontext.jsonaspacksand prints them under Read next. It also detects SvelteKit,
Strapi, Beego, Spring, the ASP.NET Core SDK, Jetpack Compose, Ktor, SwiftUI, and UIKit. map_structure.py, the structure map: one table of every file with its purpose, symbols,
and roles, plus findings for misplaced symbols (middleware declared inauth.tsis reported with
a move tomiddleware/), files mixing several roles, duplicated bodies, clashing names, synonym
verbs, component coupling metrics (Ca, Ce, I, A, D), and folder cycles; C#, JVM, and PHP
dependencies follow the type names code uses, not namespace imports.--writesaves
.clean/structure.mdand.clean/structure.json; the SessionStart hook prints the findings.
Symbol extraction covers all 21 languages with the standard library only.- Naming findings: a
nameskind reports classes, functions, methods, and (in Python,
JavaScript, and TypeScript) variables and parameters that break a Clean Code naming rule — vague,
encoded (Hungarian prefixes, a strayI), numbered (_v2,data2), a noise word (Manager,
Helper), a verb-named class, too short, off the language's own casing convention (with the
project's own majority casing overriding it where established), or a file whose one public type
is named for something else — each citing N1, N3, N4, N5, N6, G17, or G24 and judged per project
in a monorepo. - Organization findings:
family(three or more files sharing a name that import each other,
proposed as a folder named for it — Common Closure Principle, Screaming Architecture),
junk_drawer(a folder named for no concept holding production files, split by family and by
role, or renamed when it holds one concept),flat_folder(more than fifteen production files in
one folder with no grouping),unreferenced(a production file nothing imports and no role,
entry point, orentryline explains — "possibly unused", G9), andcomment_heavy(a file whose
comments are at least 40% of its non-blank lines and at least twenty in number — routed to the
new comment-cleanup workflow).structure.mdgains a Proposed moves section
(source -> destination) the clean-up campaign's placement batch consumes.
map_structure.py --changedlimits every finding, including these, to files git reports as
changed, for the newreviewcommand. Anentry <glob>line in aclean-rolesblock names
files a framework loads without an import: never unreferenced, and a folder holding only them is
no junk drawer. Files a manifest runs (pyproject[project.scripts],[project.gui-scripts],
and[project.entry-points.*]targets; package.jsonbin,main,module, andexports)
are entries without one. A junk-drawer name a convention chose is not reported: the folder-glob
home of the role it is named for (Rails'app/helpers/) or ashared/folder of components,
directives, and pipes (Angular).acceptandignore-namenow also silence naming and
organization findings, not only placement ones. skills/clean-code/scripts/reorganized intosource/(file walking, the lexer, import
parsing and resolution),symbols/(symbol extraction per language), andstructure/(roles,
findings, naming, organization, metrics, and the report), with the five CLIs
(detect_stack.py,scan_repo.py,check_boundaries.py,map_structure.py,
check_compression.py) staying at the top level so every documented command and manual
equivalent keeps working; behavior-preserving, verified by the unit tests before and after.- Role conventions in fenced
clean-rolesblocks (homes by glob, roles by name or declaration
signal), overridable per project in.clean/roles.md.allowlets a home hold other roles (a
React context file keeps its Provider and hook; an Express controller may takenext), and
accept <glob> [= symbols]records a deliberate exception so the map stops flagging it. In a
monorepo, a framework pack speaks only for the project whose manifest named its framework
(pack_scopesincontext.json),supersedeapplies within one manifest, so a Strapi CMS
never hides the React app beside it, and move suggestions and name clashes stay inside one
project. - An eval harness:
evals/grade.pygrades a run against a case's deterministic expectations
and exportsevals/evals.jsonin skill-creator's layout; 49 cases (eleven core, 38 covering 37
packs, the sixteen listed below included), andevals/triggers.jsonfor description tuning.
evals/README.mdrecords the first benchmark on ten cases: every expectation passed with the
skill, 95.5% without it, at about 48% more tokens per task. - A unit test suite (
tests/, standard libraryunittest), run byvalidate.shand CI. docs/install.md,docs/configuration.md, anddocs/pack-sources.md, the sources each pack was
checked against.scripts/check_originality.pyfor contributors: it compares shipped Markdown with the local,
gitignored books for runs of eight or more shared words. Its first run led to rewording sixteen
such runs in references that predate this release.- Agent smells A1-A10 (hallucinated API, unverified dependency, context loss, scope creep,
duplicate implementation, wrong-file gravity, phantom success, test weakening, speculative
abstraction, silent architecture drift) replace the untagged Agent Failure Modes table in
review-checklist.md, each with a signal and a response, cited beside the book's G, N, and T
IDs inchapter-map.mdandsmell-triage.md. /clean-code plan <task>(references/plan.md): reads project context, finds existing
implementations before proposing new ones, verifies every API the plan relies on against the
installed version, places the change, and writes a plan under fixed headings; edits nothing./clean-code review [files]: reviews the working tree, then staged changes, then named
files, withmap_structure.py --changed,check_boundaries.py, and the checklist; findings
first, ranked P0-P3, each with a smell ID; edits nothing.- Risk-based verification: every change is rated LOW, MEDIUM, or HIGH from its scope, blast
radius, uncertainty, and reversibility, each level naming the checks it owes before completion
(review-checklist.md, Risk Levels); the operating loop's verify step points to it.
(kyuna0312's PR #6 proposed the agent
smells, theplanandreviewcommands, risk-based verification, and planted-flaw evals; all
four landed in this release.) references/patterns.md: architecture styles (DI, IoC, MVC, MVVM, CQRS, Clean, Hexagonal,
Microservices, Event-Driven), design patterns (Repository, Unit of Work, Factory, Singleton,
Strategy, Adapter, Decorator, Observer, Command), and data-access approaches (ORM, Micro ORM,
Query Builder, Data Mapper, Active Record) — each with its intent, when it earns its place, when
it is over-engineering, its link to the books, and which packs' frameworks embody it./clean-code compress [files](references/compress.md) and
scripts/check_compression.py: rewrite a project's own instruction files (AGENTS.md,
CLAUDE.md,GEMINI.md,DESIGN.md,ARCHITECTURE.md,CONTRIBUTING.md,.cursor/.github
rule files) tersely, keeping a<name>.original.mdbackup and never touching the managed block;
the checker exits 1 when a rewrite lost a heading, a code block, an inline code span, a URL, a
rule ID, or a number, and reports the token reduction.- Comment cleanup (
references/comments.md, routed from the Load Plan andclean-up):
classifies each comment by Clean Code's kept and deleted kinds, turns "what" comments into names,
and rewrites surviving "why" comments tersely; thecomment_heavyfinding picks the files. - The minimal-code ladder, an always-on
SKILL.mdrule: before writing code, ask in order
whether it needs to exist, whether the codebase already has it, whether the standard library or
an installed dependency does it, whether it is one line; safety is never cut. - Six new eval cases graded by planted-flaw and stack-specific expectations (hallucinated-api,
unverified-success, unsafe-refactor, frontend-data-fetch, naming-cleanup, comment-cleanup), plus
eight new pack cases;grade.pygained thecommand_passesexpectation (runs a command in the
workspace, passes on exit 0) andnew_filenow accepts a list of globs.evals/README.mdrecords
a second benchmark iteration across the new cases and two of the first iteration's, with and
without the skill, on Sonnet and Haiku. - After the second benchmark:
- An explicit request widens the surgical scope. When the request names an outcome that needs an
out-of-scope fix ("make the suite pass"), the agent makes the smallest fix and reports it
separately, never by weakening a test (SKILL.mdScope Modes and the managed block). - The context gate tells the agent to open each listed pack before the first edit; naming a pack
is not reading it. The completion checklist checks it. references/tools.mdholds what each script answers, its flags, exit codes, and finding keys;
SKILL.mdkeeps one line pointing there.- The walker lists files through
git ls-files --cached --others --exclude-standard, so a
project's ignored folders drop out. It falls back toos.walkoutside git or when git ignores
the root, and still walks submodules and nested repositories. - Poetry scripts and plugins, inline
[project]script tables, setup.cfg[options.entry_points],
and extension-less package.json targets count as entry points. - Two harder planted-flaw cases (secret-logging, swallowed-error); unverified-success checks the
suite. A third, targeted benchmark iteration is recorded inevals/README.md.
- An explicit request widens the surgical scope. When the request names an outcome that needs an
Terse Content
The always-loaded managed block and SKILL.md, and every reference and pack, were rewritten in a
caveman-derived terse style — full words, imperative verbs, no filler or hedging — cutting the
top-level references by about 21% (30,263 to about 24,000 words) with no technical loss, verified
by the new check_compression.py against every rewrite. The minimal-code ladder is credited to the
ponytail plugin and the terse style to
caveman; this release adopts both as skill rules and
workflows rather than depending on either plugin, so the skill keeps working with no tooling in any
host.
Changed
SKILL.mdis a lean router, terse-rewritten to about 1,500 tokens, that opens with the
context gate: read.clean/, run the detector, read the named packs, then edit; a trivial edit
skips the gate.validate.shenforces the budgets:SKILL.mdat most 1,500 tokens, the managed
block 750, each pack 2,000. The security rule stays in the always-on rules, and the Load Plan
routes security, trust boundaries, and performance questions toprinciples.md.- The README is short; install and configuration details moved to
docs/. - The agent failure-mode and anti-loophole tables moved from
SKILL.mdtoreview-checklist.md. - Import parsing moved into
source/imports.pyand now reads Shell, PowerShell, R, and
Objective-C imports;scan_repo.pyshares the generated-file detection of the new map, which
also recognizes generated files by name (*.Designer.cs,*.g.cs,*_pb2.py,*.pb.go, and
minified or bundled*.min.js,*.min.mjs,*.min.css,*.bundle.js), so they no longer count
as large files or flood the naming findings. - Every script prints UTF-8, so non-ASCII text reaches an agent intact through a Windows pipe.
- A file counts as generated only when the comment that opens it says so, not when its prose
mentions a generated report. detect_stack.pydetects JavaScript frameworks by exactpackage.jsondependency keys, so
next-themesin a Vite app no longer reads as Next.js.- The SessionStart hook resolves pack paths against the installed skill and says nothing about
layers in a project without.clean/.
Fixed
check_boundaries.pylayer globs: a leading**/now also matches a top-level folder, and
folders that only hold sources (src/main/java,include/, R'sR/) no longer become namespace
tokens, which had classified everyjava.*import into the first declared layer.check_boundaries.pysees an import on the first line of a file that starts with a
byte-order mark, as Visual Studio writes by default; such a file could pass while breaking the
declared layers.- No script crashes on piped output in Windows when a path, name, or summary holds a
character outside the console code page;detect_stack.py --writesaves its file first. check_boundaries.pyresolves tsconfig and jsconfigpathsaliases andbaseUrlimports, so
a domain file importing@/lib/dbin a Next.js app no longer passes. An import that resolves to
a project file outside every declared layer prints a WARN line, and--jsonlists it under
unlayered_imports.- Installs and the release zip carry no Python bytecode; the installers skip
__pycache__,
and the release job fails if its archive holds any.