Clean architecture
Skill pantheon-org/tekhne/skills/software-engineering/design-principles/clean-architecture
Apply Clean Architecture principles to define layer boundaries, identify dependency violations, and structure domain vs infrastructure code. Use when designing service boundaries, separating business logic from infrastructure, evaluating hexagonal/onion/ports-and-adapters architecture, structuring module layout, or resolving dependency inversion and circular dependency issues.From its SKILL.md
npx -y skills add pantheon-org/tekhne --skill clean-architectureAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 9 stars9 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.0 KB, ~1.7k tokens by cl100k_base, as published. Nobody here has run it
Clean Architecture
Strategic architecture principles for boundaries, dependencies, and layered system design.
When to Use
- Designing service boundaries or module structure
- Evaluating dependency direction and circular dependencies
- Structuring new applications or refactoring monoliths
- Assessing where to place entities, use cases, adapters, and frameworks
- Deciding when to introduce architectural boundaries
When Not to Use
- Class-level design decisions (use solid-principles)
- Choosing structural patterns like Factory or Adapter (use design-patterns)
- Testing strategy configuration (use testable-design)
Architecture Layers
Dependency Rule: Dependencies point inward only. Inner layers know nothing about outer layers.
Layers (inner → outer): Entities → Use Cases → Interface Adapters → Frameworks & Drivers
See references/dep-inward-only.md for layer definitions and examples.
Workflow
Step 1: Identify Decision Type
Output: Classify as entity, use case, adapter, or framework decision.
Ask:
- Does this logic belong to core business rules? → Entity
- Does it orchestrate business workflows? → Use Case
- Does it translate between layers? → Adapter
- Is it external infrastructure? → Framework
Step 2: Apply Dependency Direction Checks
Output: Dependency violations with corrective actions.
Checklist:
- Dependencies point inward (no outer layers importing inner layers)
- No circular dependencies between modules
- Clear ownership of interfaces (defined by inner layers, implemented by outer layers)
- Entities remain pure (no framework or infrastructure imports)
Example:
Violation: Entity imports ORM decorator from infrastructure.
Refactor: Define entity as plain object; map to ORM in repository (adapter layer).
Step 3: Design Use Cases
Output: Use case interface with input/output ports.
Template:
// Use Case (application layer)
interface CreateOrderUseCase {
execute(input: CreateOrderInput): Promise<CreateOrderOutput>
}
// Input/Output ports (defined by use case)
interface CreateOrderInput {
userId: string
items: OrderItem[]
}
interface CreateOrderOutput {
orderId: string
status: string
}
Use cases:
- Have one responsibility (single workflow)
- Depend on abstractions (ports), not concrete implementations
- Orchestrate entities and gateways
- Contain no presentation logic (formatting, HTTP, UI)
Step 4: Define Boundaries with Adapters
Output: Adapter interfaces (ports) and implementations.
- Controllers: HTTP requests → use case input
- Presenters: Use case output → HTTP response
- Gateways: Use case calls → database/API operations
- Repositories: Entity persistence → database operations
Example:
// Port (defined by use case layer)
interface IOrderRepository {
save(order: Order): Promise<void>
findById(id: string): Promise<Order | null>
}
// Adapter (infrastructure layer)
class PostgresOrderRepository implements IOrderRepository {
async save(order: Order): Promise<void> {
// Map entity to ORM, persist
}
}
Step 5: Place Framework Code at Edges
Output: Framework integrations isolated in outermost layer.
Keep frameworks (Express, NestJS, TypeORM, React) in the infrastructure/adapter layer:
- DI container at application edge
- ORM configurations in infrastructure
- Web server in infrastructure
- Domain remains framework-free
Example:
BAD: Entity uses @Entity decorator from TypeORM.
GOOD: Entity is plain TypeScript; repository maps to TypeORM in infrastructure.
Step 6: Document Boundary Decisions
Output: ADR with rationale, alternatives, and risks.
Template:
Decision: Extract authentication into separate bounded context.
Rationale: Auth has independent lifecycle and team ownership.
Alternatives:
- Keep in monolith (simpler, tightly coupled)
- Partial boundary (YAGNI, easier to extract later)
Chosen: Full bounded context (clear ownership, independent deployment)
Risks: Network calls add latency; requires distributed transaction handling.
Anti-Patterns
NEVER allow circular dependencies
BAD: Module A imports B and B imports A.
GOOD: Extract shared contract/module and invert dependencies.
NEVER let entities depend on frameworks
BAD: Entity imports ORM decorators, framework types, or infrastructure.
GOOD: Entities are plain objects; adapters handle framework mapping.
NEVER put business logic in controllers
BAD: Controller validates, calculates, and persists data.
GOOD: Controller calls use case; use case orchestrates business logic.
NEVER bypass interface contracts
BAD: Use case instantiates concrete PostgresRepository.
GOOD: Use case depends on IRepository interface; DI provides implementation.
NEVER design boundaries for imagined future requirements
BAD: Add full hexagonal architecture "in case" of future DB migration.
GOOD: Solve current need; refactor when trigger appears (YAGNI).
Quick Commands
# Find dependency direction violations
rg -n "import.*infrastructure.*from.*domain|import.*adapter.*from.*entity" src
# Find circular dependencies
nx graph
# Find framework leakage into domain
rg -n "@Entity|@Injectable|@Component" src/domain
References
Dependencies: inward-only · acyclic · data crossing boundaries · no framework imports
Components: screaming architecture · stable dependencies
Boundaries: cost awareness · defer decisions · service internal architecture
Entities: purity · rich not anemic · encapsulate invariants · value objects · no persistence awareness
Use Cases: isolation · explicit dependencies · orchestrates not implements · input/output ports · no presentation logic · transaction boundary
Adapters: gateway abstraction · thin controller · mapper translation · presenter formats
Frameworks: DI at edge · domain purity · ORM in infrastructure · web in infrastructure
What ships with it: 34 files
99.8 KB alongside SKILL.md
evals/
- scenario-01.md3.3 KB
- scenario-02.md3.1 KB
- scenario-03.md3.2 KB
- scenario-04.md3.1 KB
- scenario-05.md3.2 KB
references/
- adapt-controller-thin.md3.2 KB
- adapt-gateway-abstraction.md3.4 KB
- adapt-mapper-translation.md2.7 KB
- adapt-presenter-formats.md3.4 KB
- bound-boundary-cost-awareness.md3.1 KB
- bound-defer-decisions.md3.0 KB
- bound-service-internal-architecture.md5.7 KB
- comp-common-reuse.md2.1 KB
- comp-screaming-architecture.md2.2 KB
- comp-stable-dependencies.md3.5 KB
- dep-acyclic-dependencies.md2.3 KB
- dep-data-crossing-boundaries.md1.9 KB
- dep-inward-only.md2.0 KB
- dep-no-framework-imports.md2.1 KB
- entity-encapsulate-invariants.md2.8 KB
- entity-no-persistence-awareness.md2.5 KB
- entity-pure-business-rules.md1.9 KB
- entity-rich-not-anemic.md3.2 KB
- entity-value-objects.md2.4 KB
- frame-di-container-edge.md3.0 KB
- frame-domain-purity.md3.5 KB
- frame-orm-in-infrastructure.md3.1 KB
- frame-web-in-infrastructure.md3.5 KB
- usecase-explicit-dependencies.md3.2 KB
- usecase-input-output-ports.md2.7 KB
- usecase-no-presentation-logic.md3.1 KB
- usecase-orchestrates-not-implements.md2.9 KB
- usecase-single-responsibility.md3.0 KB
- usecase-transaction-boundary.md2.6 KB
Gives 0 of the 12 instructions most architecture codebase skills give in ~1.7k tokens
Counted across 811 of the 1,134 authors here whose files we hold, read 2026-08-07
- Ask the user which candidate to explorein 45 of 811, across 15 files
- Apply the deletion test to suspected shallow modulesin 43 of 811, across 15 files
- Read any relevant architecture decision records firstin 31 of 811, across 8 files
- Use exact glossary terms in every suggestionin 30 of 811, across 10 files
- Accept dependencies instead of creating themin 24 of 811, across 5 files
- Include before and after visualisations for each candidatein 24 of 811, across 5 files
- Read the domain glossary before exploringin 24 of 811, across 6 files
- Return results instead of producing side effectsin 23 of 811, across 4 files
- Explore the codebase for shallow modules and frictionin 23 of 811, across 3 files
- Introduce seams only where things varyin 22 of 811, across 3 files
- Reduce the number of methodsin 21 of 811, across 2 files
- Design deep modules with small interfacesin 21 of 811, across 3 files
Said here and by no other author read
- classify decisions as entity, use case, adapter, or framework
- keep presentation logic out of use cases
- isolate framework code in the outermost layer
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.