/unfolding-architecture
This skill should be used when the user asks to "design the architecture", "should I add a service layer", "add an abstraction", "introduce an interface", "separate concerns", "add a repository", "use hexagonal architecture", "add domain events", "split into layers", "add ports
Claude Code
$ npx -y skills add t1/tdder --skill unfolding-architecture --agent claude-code
Codex
$ npx skills add t1/tdder --skill unfolding-architecture -a codex -y
Cursor
$ npx skills add t1/tdder --skill unfolding-architecture -a cursor -y
Gemini CLI
$ npx skills add t1/tdder --skill unfolding-architecture -a gemini-cli -y
GitHub Copilot
$ npx skills add t1/tdder --skill unfolding-architecture -a github-copilot -y
OpenCode
$ npx skills add t1/tdder --skill unfolding-architecture -a opencode -y
Windsurf
$ npx skills add t1/tdder --skill unfolding-architecture -a windsurf -y
SKILL.md
unfolding-architecture.SKILL.mdname: unfolding-architecture
description: >
This skill should be used when the user asks to "design the architecture", "should I add a service layer",
"add an abstraction", "introduce an interface", "separate concerns", "add a repository",
"use hexagonal architecture", "add domain events", "split into layers", "add ports and adapters",
"decouple this", "add an anti-corruption layer", "review package structure",
"apply a design pattern", "which design pattern fits", "introduce a factory/strategy/builder",
or when considering architectural changes during a TDD refactor phase.
It also contains guides when starting a new project.
version: 0.1.0
Unfolding Architecture
Progressive architectural decisions: start simple, add complexity only when it reduces complexity.
Architecture is not a blueprint drawn before construction. It unfolds from working code under concrete pressure. Each dimension of architecture starts at its simplest form (Level 0) and only moves to a higher level when a specific, demonstrable problem forces the change.
**Central creed: code quality = maintaining long-term speed of development.** Every architectural decision — unfolding a dimension, applying a design pattern, or removing one — is judged by whether it keeps the code easy to understand and change tomorrow.
Default Starting Point
**Level 0 in all dimensions.** No deviation without a concrete reason backed by a violated constraint, or measurable complexity increase. "It might be useful later" is never a valid reason to unfold.
Dimensions
1. Data vs Logic
| Level | Style | Description | |-------|------------------------------------|-------------------------------------------------------------------------------------------------------------------| | 0 | OOP: data + logic together | Data and the logic that operates on it live in the same class. Logic hides data. This is the natural OOP default. | | 1 | DOP: separate data from algorithms | Stable data structures with varying algorithms applied externally. Data is transparent; logic is separate. |
**Unfold to Level 1 when:**
- Multiple independent algorithms need to operate on the same data
- Data structures are stable but processing varies significantly
- Serialization/deserialization concerns conflict with behavior encapsulation
**Do NOT unfold when:**
- Data and logic change together (they belong together)
- There is only a hand full of algorithms per data structure that are closely related to the data
- The separation would scatter related behavior across files
2. Indirection
| Level | Style | Description | |-------|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 0 | Direct dependencies | Everything knows about everything it uses. No interfaces, no layers, no DTOs. Persistence lives next to domain. | | 1 | Targeted abstraction | Interface or anti-corruption layer at a specific pain point — persistence, external API, or unstable component. | | 2 | Ports & adapters (hexagonal) | Full separation of domain from infrastructure via IoC: the domain defines ports (interfaces), adapters implement them, dependencies point inward. Persistence is just one adapter among many. A composition root wires adapters to ports. |
**Unfold to Level 1 when:**
- A component has multiple concrete implementations that must be swappable
- A dependency crosses a deployment boundary (e.g., external service)
- Testing requires replacing a real dependency with a test double, e.g. calling an external service
- An external system's model leaks into and distorts the domain model
- An external API returns data in a shape that does not match domain concepts
- Changes in one component frequently force changes in an unrelated component
- Persistence technology needs to change and the domain should not be affected
**Unfold to Level 2 when:**
- Multiple adapters exist for the same port (e.g., database + in-memory for tests,
but there is no suitable abstraction layer available in the platform, e.g. an EntityManager)
- It becomes too complex to test the domain in isolation from real infrastructure
- The system has many distinct infrastructure concerns (persistence, messaging, external APIs, etc.)
that would clutter the domain
**Do NOT unfold when:**
- Only one implementation exists, and it can be seen as an implementation or model detail of the domain
- The "interface" would mirror the class 1:1 (interface bloat)
- The coupling is between genuinely related concepts (cohesion, not coupling)
- DTOs or DB Entities would be identical copies of domain objects (except for some annotations, etc.)
- The "boundary" is between two internal components that change together
- The application has a single persistence mechanism and no external integrations
**Note:** Even hexagonal architecture can evolve step-by-step. You do not need to introduce all ports and adapters at once. Start with a single targeted abstraction (Level 1) where the pressure is highest, then add more ports as concrete needs arise. Full hexagonal (Level 2) is the result of multiple incremental unfoldings, not a sing
Read more
name: unfolding-architecture description: > This skill should be used when the user asks to "design the architecture", "should I add a service layer", "add an abstraction", "introduce an interface", "separate concerns", "add a repository", "use hexagonal architecture", "add domain events", "split into layers", "add ports and adapters", "decouple this", "add an anti-corruption layer", "review package structure", "apply a design pattern", "which design pattern fits", "introduce a factory/strategy/builder", or when considering architectural changes during a TDD refactor phase. It also contains guides when starting a new project. version: 0.1.0
Unfolding Architecture
Progressive architectural decisions: start simple, add complexity only when it reduces complexity.
Architecture is not a blueprint drawn before construction. It unfolds from working code under concrete pressure. Each dimension of architecture starts at its simplest form (Level 0) and only moves to a higher level when a specific, demonstrable problem forces the change.
**Central creed: code quality = maintaining long-term speed of development.** Every architectural decision — unfolding a dimension, applying a design pattern, or removing one — is judged by whether it keeps the code easy to understand and change tomorrow.
Default Starting Point
**Level 0 in all dimensions.** No deviation without a concrete reason backed by a violated constraint, or measurable complexity increase. "It might be useful later" is never a valid reason to unfold.
Dimensions
1. Data vs Logic
| Level | Style | Description | |-------|------------------------------------|-------------------------------------------------------------------------------------------------------------------| | 0 | OOP: data + logic together | Data and the logic that operates on it live in the same class. Logic hides data. This is the natural OOP default. | | 1 | DOP: separate data from algorithms | Stable data structures with varying algorithms applied externally. Data is transparent; logic is separate. |
**Unfold to Level 1 when:**
- Multiple independent algorithms need to operate on the same data
- Data structures are stable but processing varies significantly
- Serialization/deserialization concerns conflict with behavior encapsulation
**Do NOT unfold when:**
- Data and logic change together (they belong together)
- There is only a hand full of algorithms per data structure that are closely related to the data
- The separation would scatter related behavior across files
2. Indirection
| Level | Style | Description | |-------|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 0 | Direct dependencies | Everything knows about everything it uses. No interfaces, no layers, no DTOs. Persistence lives next to domain. | | 1 | Targeted abstraction | Interface or anti-corruption layer at a specific pain point — persistence, external API, or unstable component. | | 2 | Ports & adapters (hexagonal) | Full separation of domain from infrastructure via IoC: the domain defines ports (interfaces), adapters implement them, dependencies point inward. Persistence is just one adapter among many. A composition root wires adapters to ports. |
**Unfold to Level 1 when:**
- A component has multiple concrete implementations that must be swappable
- A dependency crosses a deployment boundary (e.g., external service)
- Testing requires replacing a real dependency with a test double, e.g. calling an external service
- An external system's model leaks into and distorts the domain model
- An external API returns data in a shape that does not match domain concepts
- Changes in one component frequently force changes in an unrelated component
- Persistence technology needs to change and the domain should not be affected
**Unfold to Level 2 when:**
- Multiple adapters exist for the same port (e.g., database + in-memory for tests,
but there is no suitable abstraction layer available in the platform, e.g. an EntityManager)
- It becomes too complex to test the domain in isolation from real infrastructure
- The system has many distinct infrastructure concerns (persistence, messaging, external APIs, etc.)
that would clutter the domain
**Do NOT unfold when:**
- Only one implementation exists, and it can be seen as an implementation or model detail of the domain
- The "interface" would mirror the class 1:1 (interface bloat)
- The coupling is between genuinely related concepts (cohesion, not coupling)
- DTOs or DB Entities would be identical copies of domain objects (except for some annotations, etc.)
- The "boundary" is between two internal components that change together
- The application has a single persistence mechanism and no external integrations
**Note:** Even hexagonal architecture can evolve step-by-step. You do not need to introduce all ports and adapters at once. Start with a single targeted abstraction (Level 1) where the pressure is highest, then add more ports as concrete needs arise. Full hexagonal (Level 2) is the result of multiple incremental unfoldings, not a sing
A plugin for pi, Claude Code, and OpenCode that guides AI agents through disciplined Test-Driven Development and Clean Code practices. Note that currently this is WORK IN PROGRESS! I'm not even trying to keep it stable or tested.
Other skills on tdder.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about unfolding-architecture.
- Which coding agents can use unfolding-architecture?
- unfolding-architecture installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

