clean-with-fdd
Installation
SKILL.md
Clean with FDD
Audit and plan migration toward Clean Architecture + Feature-Driven Development, in any language, with framework- and third-party-agnostic business logic. This skill only audits and plans — it never writes production code. State is persisted so a session can resume mid-workflow.
Code examples in these docs are mostly TypeScript for concreteness, but every rule applies to Python, Go, Rust, Java, Kotlin, C#, Ruby, PHP, etc. Per-language guidance lives in FP-DISCIPLINE.md.
Core rules
- Frameworks are delivery only. Web frameworks (React/Vue/Next/Express/Nest/Hono/Django/Flask/FastAPI/Rails/Spring/ASP.NET/Gin/Axum/etc.) live exclusively in controllers (backend) or presenters (frontend). Domain and use-cases must compile with zero framework imports.
- Third-party-agnostic business logic. Stripe, Prisma, Mongoose, SQLAlchemy, GORM, Diesel, Hibernate, Axios, etc. are reached through ports in the use-case layer; adapters live outside the domain.
- Favor data + functions over heavy OOP in business logic. Entities are typed values; use-cases are functions; adapters are constructed via factories or lightweight injection. JS/TS goes further — no classes at all because of eslint/biome lint friction. Other languages follow the spirit (small data classes / records / structs are fine; deep inheritance and framework-bound base classes are not). See FP-DISCIPLINE.md.
- Sum types + value-typed errors. Use the language's tagged-union equivalent (TS discriminated unions, Rust enums, Kotlin sealed classes, Python
Literal-tagged dataclasses ormatchtypes, Go constant-tagged structs, C# records w/ pattern match). Errors in domain/use-cases are returned as values (Result<T, E>,Either,(T, error),Outcome<T>), not thrown. - Dependency rule. Inner layers know nothing of outer ones. Imports point inward only. See LAYERS.md.
- Feature slices + shared kernel.
<src>/features/<feature>/self-contained;<src>/shared/{domain,ports}/for cross-feature primitives. See STRUCTURE.md.
Full vocabulary in LANGUAGE.md. Use these terms exactly — don't drift into "service," "component," "module," "boundary."