skills/clean-architecture/SKILL.md
Language-agnostic Clean Architecture principles: dependency rule, layer separation, ports & adapters, screaming architecture, and bounded contexts. Trigger: When designing service architecture, reviewing layer boundaries, onboarding to the codebase, or deciding where code belongs.
npx skillsauth add 333-333-333/agents clean-architectureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill defines the principles. For language-specific implementation, see:
go-microservice-scaffold skill (directory structure, naming, scaffold steps)flutter-scaffold skill (feature-based structure, layers)This is the ONE rule that makes Clean Architecture work. Everything else follows from it.
┌─────────────────────────────────────┐
│ Infrastructure │ Frameworks, drivers, UI, DB
│ ┌───────────────────────────────┐ │
│ │ Application │ │ Use cases, orchestration
│ │ ┌─────────────────────────┐ │ │
│ │ │ Domain │ │ │ Entities, value objects, ports
│ │ └─────────────────────────┘ │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
Dependencies ALWAYS point INWARD.
Inner layers NEVER know about outer layers.
Concretely:
The dependency rule exists so that:
The domain layer contains the business rules of your system. It has no dependencies on anything external.
| Contains | Description | Example |
|----------|-------------|---------|
| Entities | Objects with identity and lifecycle | Booking, User, Pet |
| Value Objects | Immutable objects defined by their attributes | Money, Email, BookingStatus |
| Ports (interfaces) | Contracts that infrastructure must fulfill | BookingRepository, PaymentGateway |
| Domain Errors | Business rule violations | ErrBookingOverlap, ErrInsufficientFunds |
| Domain Services | Logic that doesn't belong to a single entity | PricingCalculator |
Rules:
The application layer contains use cases — the specific things your system can do.
| Contains | Description | Example |
|----------|-------------|---------|
| Use Cases / Services | Orchestrate domain objects to fulfill a request | CreateBooking, CancelBooking |
| DTOs | Input/output structures for use cases | CreateBookingInput, BookingOutput |
| Application Errors | Errors specific to use case orchestration | ErrBookingNotFound (repo returned nil) |
Rules:
The infrastructure layer contains adapters — concrete implementations of domain ports.
| Contains | Description | Example |
|----------|-------------|---------|
| Handlers | HTTP/gRPC entry points that call use cases | BookingHandler |
| Repositories | Database implementations of domain ports | PostgresBookingRepository |
| Messaging | Message broker adapters | NATSPublisher, NATSSubscriber |
| External Services | Third-party API clients | FlowPaymentGateway, FCMNotificationSender |
| Configuration | Environment loading, server setup | Config, Server |
Rules:
Ports & Adapters (Hexagonal Architecture) is the mechanism that enforces the dependency rule.
┌──────────────────────┐
HTTP Handler ──▶ │ │ ──▶ PostgreSQL Repository
│ Domain + Use Cases │
gRPC Handler ──▶ │ │ ──▶ NATS Publisher
│ (defines ports) │
CLI Command ──▶ │ │ ──▶ S3 Object Store
└──────────────────────┘
▲ Driving adapters Driven adapters ▶
(call the system) (called by the system)
The domain defines WHAT it needs (ports). Infrastructure decides HOW to provide it (adapters).
"Your architecture should scream the business domain, not the framework." — Robert C. Martin
The directory structure communicates WHAT the system does, not how it's built.
| Bad (screams framework) | Good (screams domain) |
|---|---|
| controllers/ | booking/ |
| models/ | caregiver/ |
| services/ | payment/ |
| repositories/ | notification/ |
| utils/ | pet/ |
A new developer should understand the business domain by looking at the directory structure, without reading a single line of code.
Each service (or module) owns ONE bounded context — a clear boundary around a business domain.
| Principle | Rule | |-----------|------| | Own your data | Each context has its own database/schema. Never share tables. | | Explicit boundaries | Communication between contexts goes through defined interfaces (APIs, events). | | Ubiquitous language | Each context uses its own terminology. A "User" in auth ≠ "User" in booking. | | No circular dependencies | If A depends on B and B depends on A, merge them or extract a third context. |
Use this decision tree when you're unsure:
Does it represent a business concept (entity, rule, constraint)?
→ Domain layer
Does it orchestrate multiple domain objects to fulfill a use case?
→ Application layer
Does it talk to a database, API, message broker, or framework?
→ Infrastructure layer
Does it define WHAT is needed without specifying HOW?
→ Domain layer (as a port/interface)
Does it implement a domain interface with a specific technology?
→ Infrastructure layer (as an adapter)
Is it a DTO that enters or leaves a use case?
→ Application layer
Is it configuration, logging setup, or server bootstrap?
→ Infrastructure layer (shared/)
| Violation | Why it's bad | Fix |
|-----------|-------------|-----|
| Domain imports database/sql | Domain now depends on a specific database | Define a repository interface in domain |
| Use case imports gin.Context | Application tied to HTTP framework | Handler extracts data, passes plain DTOs |
| Handler contains business logic | Logic untestable without HTTP setup | Move logic to use case, handler just delegates |
| Domain entity has JSON tags | Domain coupled to serialization format | Use separate DTOs in infrastructure |
| Shared database between services | Tight coupling, can't evolve independently | Each service owns its data |
| utils/ package | Grab bag with no cohesion | Put helpers where they belong by domain |
Clean architecture makes testing natural:
| Layer | Test type | Dependencies | |-------|-----------|-------------| | Domain | Unit tests | None — pure logic | | Application | Unit tests | In-memory implementations of ports | | Infrastructure | Integration tests | Real databases (testcontainers), real APIs | | Full stack | E2E tests | All layers wired together |
The dependency rule means domain and application tests are fast, isolated, and reliable — they don't need databases, network, or frameworks.
testing
Review Flutter components and screens for UX/UI compliance. Trigger: When user invokes /ux-review command or requests UX audit.
development
TypeScript strict patterns and best practices. Trigger: When implementing or refactoring TypeScript in .ts/.tsx (types, interfaces, generics, const maps, type guards, removing any, tightening unknown).
testing
Testing philosophy and strategy for every feature: test pyramid, mandatory levels per change type, completion checklist, and skill delegation. Trigger: When planning tests for a feature, reviewing test coverage, defining acceptance criteria, or asking what tests a change needs.
development
Terraform security practices: sensitive variables, secret management, state protection, .gitignore patterns, and CI/CD credential handling. Trigger: When handling secrets in Terraform, configuring state backends, reviewing .gitignore for Terraform, or setting up CI/CD pipelines for infrastructure.